/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 | 168 | vlc_module_begin () |
52 | 84 | set_subcategory( SUBCAT_SOUT_PACKETIZER ) |
53 | 84 | set_description( N_("MPEG4 video packetizer") ) |
54 | 84 | set_capability( "video packetizer", 50 ) |
55 | 168 | set_callbacks( Open, Close ) |
56 | 84 | 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 | | int64_t i_last_time_ref; |
75 | | int64_t i_time_ref; |
76 | | int64_t i_last_time; |
77 | | int64_t i_last_timeincr; |
78 | | |
79 | | unsigned int i_flags; |
80 | | |
81 | | int i_fps_num; |
82 | | int i_fps_den; |
83 | | |
84 | | bool b_frame; |
85 | | |
86 | | /* Current frame being built */ |
87 | | block_t *p_frame; |
88 | | block_t **pp_last; |
89 | | } decoder_sys_t; |
90 | | |
91 | | static block_t *Packetize( decoder_t *, block_t ** ); |
92 | | static void PacketizeFlush( decoder_t * ); |
93 | | |
94 | | static void PacketizeReset( void *p_private, bool b_broken ); |
95 | | static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t * ); |
96 | | static int PacketizeValidate( void *p_private, block_t * ); |
97 | | |
98 | | static block_t *ParseMPEGBlock( decoder_t *, block_t * ); |
99 | | static int ParseVOL( decoder_t *, es_format_t *, uint8_t *, int ); |
100 | | static int ParseVO( decoder_t *, block_t * ); |
101 | | static int ParseVOP( decoder_t *, block_t * ); |
102 | | static int vlc_log2( unsigned int ); |
103 | | |
104 | | #define VIDEO_OBJECT_MASK 0x01f |
105 | | #define VIDEO_OBJECT_LAYER_MASK 0x00f |
106 | | |
107 | | #define VIDEO_OBJECT_START_CODE 0x100 |
108 | 1.12M | #define VIDEO_OBJECT_LAYER_START_CODE 0x120 |
109 | 416k | #define RESERVED_START_CODE 0x130 |
110 | 825k | #define VISUAL_OBJECT_SEQUENCE_START_CODE 0x1b0 |
111 | 825k | #define VISUAL_OBJECT_SEQUENCE_END_CODE 0x1b1 |
112 | 412k | #define USER_DATA_START_CODE 0x1b2 |
113 | | #define GROUP_OF_VOP_START_CODE 0x1b3 |
114 | | #define VIDEO_SESSION_ERROR_CODE 0x1b4 |
115 | 279k | #define VISUAL_OBJECT_START_CODE 0x1b5 |
116 | 542k | #define VOP_START_CODE 0x1b6 |
117 | | #define FACE_OBJECT_START_CODE 0x1ba |
118 | | #define FACE_OBJECT_PLANE_START_CODE 0x1bb |
119 | | #define MESH_OBJECT_START_CODE 0x1bc |
120 | | #define MESH_OBJECT_PLANE_START_CODE 0x1bd |
121 | | #define STILL_TEXTURE_OBJECT_START_CODE 0x1be |
122 | | #define TEXTURE_SPATIAL_LAYER_START_CODE 0x1bf |
123 | | #define TEXTURE_SNR_LAYER_START_CODE 0x1c0 |
124 | | |
125 | | static const uint8_t p_mp4v_startcode[3] = { 0x00, 0x00, 0x01 }; |
126 | | |
127 | | /***************************************************************************** |
128 | | * Open: probe the packetizer and return score |
129 | | *****************************************************************************/ |
130 | | static int Open( vlc_object_t *p_this ) |
131 | 68.3k | { |
132 | 68.3k | decoder_t *p_dec = (decoder_t*)p_this; |
133 | 68.3k | decoder_sys_t *p_sys; |
134 | | |
135 | 68.3k | if( p_dec->fmt_in->i_codec != VLC_CODEC_MP4V ) |
136 | 61.1k | return VLC_EGENERIC; |
137 | | |
138 | | /* Allocate the memory needed to store the decoder's structure */ |
139 | 7.24k | if( ( p_dec->p_sys = p_sys = malloc( sizeof(decoder_sys_t) ) ) == NULL ) |
140 | 0 | return VLC_ENOMEM; |
141 | 7.24k | memset( p_sys, 0, sizeof(decoder_sys_t) ); |
142 | | |
143 | | /* Misc init */ |
144 | 7.24k | packetizer_Init( &p_sys->packetizer, |
145 | 7.24k | p_mp4v_startcode, sizeof(p_mp4v_startcode), startcode_FindAnnexB, |
146 | 7.24k | NULL, 0, 4, |
147 | 7.24k | PacketizeReset, PacketizeParse, PacketizeValidate, NULL, |
148 | 7.24k | p_dec ); |
149 | | |
150 | 7.24k | p_sys->p_frame = NULL; |
151 | 7.24k | p_sys->pp_last = &p_sys->p_frame; |
152 | | |
153 | | /* Setup properties */ |
154 | 7.24k | es_format_Copy( &p_dec->fmt_out, p_dec->fmt_in ); |
155 | 7.24k | p_dec->fmt_out.i_codec = VLC_CODEC_MP4V; |
156 | | |
157 | 7.24k | if( p_dec->fmt_out.i_extra ) |
158 | 1.94k | { |
159 | | /* We have a vol */ |
160 | 1.94k | msg_Dbg( p_dec, "opening with vol size: %zu", p_dec->fmt_out.i_extra ); |
161 | 1.94k | ParseVOL( p_dec, &p_dec->fmt_out, |
162 | 1.94k | p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); |
163 | 1.94k | } |
164 | | |
165 | | /* Set callback */ |
166 | 7.24k | p_dec->pf_packetize = Packetize; |
167 | 7.24k | p_dec->pf_flush = PacketizeFlush; |
168 | 7.24k | p_dec->pf_get_cc = NULL; |
169 | | |
170 | 7.24k | return VLC_SUCCESS; |
171 | 7.24k | } |
172 | | |
173 | | /***************************************************************************** |
174 | | * Close: clean up the packetizer |
175 | | *****************************************************************************/ |
176 | | static void Close( vlc_object_t *p_this ) |
177 | 7.24k | { |
178 | 7.24k | decoder_t *p_dec = (decoder_t*)p_this; |
179 | 7.24k | decoder_sys_t *p_sys = p_dec->p_sys; |
180 | | |
181 | 7.24k | packetizer_Clean( &p_sys->packetizer ); |
182 | 7.24k | if( p_sys->p_frame ) |
183 | 1.71k | block_ChainRelease( p_sys->p_frame ); |
184 | 7.24k | free( p_sys ); |
185 | 7.24k | } |
186 | | |
187 | | /**************************************************************************** |
188 | | * Packetize: the whole thing |
189 | | ****************************************************************************/ |
190 | | static block_t *Packetize( decoder_t *p_dec, block_t **pp_block ) |
191 | 102k | { |
192 | 102k | decoder_sys_t *p_sys = p_dec->p_sys; |
193 | | |
194 | 102k | return packetizer_Packetize( &p_sys->packetizer, pp_block ); |
195 | 102k | } |
196 | | |
197 | | static void PacketizeFlush( decoder_t *p_dec ) |
198 | 0 | { |
199 | 0 | decoder_sys_t *p_sys = p_dec->p_sys; |
200 | |
|
201 | 0 | packetizer_Flush( &p_sys->packetizer ); |
202 | 0 | } |
203 | | |
204 | | /***************************************************************************** |
205 | | * Helpers: |
206 | | *****************************************************************************/ |
207 | | static void PacketizeReset( void *p_private, bool b_flush ) |
208 | 33.8k | { |
209 | 33.8k | decoder_t *p_dec = p_private; |
210 | 33.8k | decoder_sys_t *p_sys = p_dec->p_sys; |
211 | | |
212 | 33.8k | if( b_flush ) |
213 | 0 | { |
214 | 0 | if( p_sys->p_frame ) |
215 | 0 | block_ChainRelease( p_sys->p_frame ); |
216 | 0 | p_sys->p_frame = NULL; |
217 | 0 | p_sys->pp_last = &p_sys->p_frame; |
218 | 0 | } |
219 | | |
220 | 33.8k | p_sys->i_interpolated_pts = |
221 | 33.8k | p_sys->i_interpolated_dts = |
222 | 33.8k | p_sys->i_last_ref_pts = VLC_TICK_INVALID; |
223 | | |
224 | 33.8k | p_sys->i_last_time_ref = |
225 | 33.8k | p_sys->i_time_ref = |
226 | 33.8k | p_sys->i_last_time = |
227 | 33.8k | p_sys->i_last_timeincr = 0; |
228 | 33.8k | } |
229 | | |
230 | | static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t *p_block ) |
231 | 412k | { |
232 | 412k | decoder_t *p_dec = p_private; |
233 | 412k | const vlc_tick_t i_dts = p_block->i_dts; |
234 | 412k | const vlc_tick_t i_pts = p_block->i_pts; |
235 | | |
236 | 412k | block_t *p_au = ParseMPEGBlock( p_dec, p_block ); |
237 | | |
238 | 412k | *pb_ts_used = p_au && p_au->i_dts == i_dts && p_au->i_pts == i_pts; |
239 | | |
240 | 412k | return p_au; |
241 | 412k | } |
242 | | |
243 | | |
244 | | static int PacketizeValidate( void *p_private, block_t *p_au ) |
245 | 12.4k | { |
246 | 12.4k | decoder_t *p_dec = p_private; |
247 | 12.4k | decoder_sys_t *p_sys = p_dec->p_sys; |
248 | | |
249 | | /* We've just started the stream, wait for the first PTS. |
250 | | * We discard here so we can still get the sequence header. */ |
251 | 12.4k | if( p_sys->i_interpolated_pts == VLC_TICK_INVALID && |
252 | 830 | p_sys->i_interpolated_dts == VLC_TICK_INVALID ) |
253 | 689 | { |
254 | 689 | msg_Dbg( p_dec, "need a starting pts/dts" ); |
255 | 689 | return VLC_EGENERIC; |
256 | 689 | } |
257 | | |
258 | | /* When starting the stream we can have the first frame with |
259 | | * a null DTS (i_interpolated_pts is initialized to 0) */ |
260 | 11.7k | if( p_au->i_dts == VLC_TICK_INVALID ) |
261 | 166 | p_au->i_dts = p_au->i_pts; |
262 | 11.7k | return VLC_SUCCESS; |
263 | 12.4k | } |
264 | | |
265 | | /***************************************************************************** |
266 | | * ParseMPEGBlock: Re-assemble fragments into a block containing a picture |
267 | | *****************************************************************************/ |
268 | | static block_t *ParseMPEGBlock( decoder_t *p_dec, block_t *p_frag ) |
269 | 412k | { |
270 | 412k | decoder_sys_t *p_sys = p_dec->p_sys; |
271 | 412k | block_t *p_pic = NULL; |
272 | | |
273 | 412k | if( p_frag->i_buffer < 4 ) |
274 | 0 | return p_frag; |
275 | | |
276 | 412k | const uint32_t i_startcode = GetDWBE( p_frag->p_buffer ); |
277 | 412k | if( i_startcode == VISUAL_OBJECT_SEQUENCE_START_CODE || |
278 | 412k | i_startcode == VISUAL_OBJECT_SEQUENCE_END_CODE || |
279 | 412k | i_startcode == USER_DATA_START_CODE ) |
280 | 4.27k | { /* VOS and USERDATA */ |
281 | | #if 0 |
282 | | /* Remove VOS start/end code from the original stream */ |
283 | | block_Release( p_frag ); |
284 | | #else |
285 | | /* Append the block for now since ts/ps muxers rely on VOL |
286 | | * being present in the stream */ |
287 | 4.27k | block_ChainLastAppend( &p_sys->pp_last, p_frag ); |
288 | 4.27k | #endif |
289 | 4.27k | return NULL; |
290 | 4.27k | } |
291 | 408k | else if( i_startcode >= VIDEO_OBJECT_LAYER_START_CODE && |
292 | 267k | i_startcode < RESERVED_START_CODE ) |
293 | 105k | { |
294 | | /* Copy the complete VOL */ |
295 | 105k | if( (size_t)p_dec->fmt_out.i_extra != p_frag->i_buffer || |
296 | 24.0k | ( p_frag->i_buffer && memcmp(p_dec->fmt_out.p_extra, |
297 | 24.0k | p_frag->p_buffer, p_frag->i_buffer) ) ) |
298 | 85.0k | { |
299 | 85.0k | void *p_realloc = realloc( p_dec->fmt_out.p_extra, p_frag->i_buffer ); |
300 | 85.0k | if( p_realloc ) |
301 | 85.0k | { |
302 | 85.0k | p_dec->fmt_out.p_extra = p_realloc; |
303 | 85.0k | p_dec->fmt_out.i_extra = p_frag->i_buffer; |
304 | 85.0k | memcpy( p_realloc, p_frag->p_buffer, p_frag->i_buffer ); |
305 | 85.0k | } |
306 | 85.0k | } |
307 | 105k | ParseVOL( p_dec, &p_dec->fmt_out, |
308 | 105k | p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); |
309 | | |
310 | | #if 0 |
311 | | /* Remove from the original stream */ |
312 | | block_Release( p_frag ); |
313 | | #else |
314 | | /* Append the block for now since ts/ps muxers rely on VOL |
315 | | * being present in the stream */ |
316 | 105k | block_ChainLastAppend( &p_sys->pp_last, p_frag ); |
317 | 105k | #endif |
318 | 105k | return NULL; |
319 | 105k | } |
320 | 303k | else |
321 | 303k | { |
322 | 303k | if( !p_dec->fmt_out.i_extra ) |
323 | 24.0k | { |
324 | 24.0k | msg_Warn( p_dec, "waiting for VOL" ); |
325 | 24.0k | block_Release( p_frag ); |
326 | 24.0k | return NULL; |
327 | 24.0k | } |
328 | | |
329 | | /* Append the block */ |
330 | 279k | block_ChainLastAppend( &p_sys->pp_last, p_frag ); |
331 | 279k | } |
332 | | |
333 | 279k | if( i_startcode == VISUAL_OBJECT_START_CODE ) |
334 | 7.83k | { |
335 | 7.83k | ParseVO( p_dec, p_frag ); |
336 | 7.83k | } |
337 | 271k | else |
338 | 271k | if( i_startcode == VOP_START_CODE && |
339 | 15.0k | ParseVOP( p_dec, p_frag ) == VLC_SUCCESS ) |
340 | 12.4k | { |
341 | | /* We are dealing with a VOP */ |
342 | 12.4k | p_pic = block_ChainGather( p_sys->p_frame ); |
343 | 12.4k | p_pic->i_flags = p_sys->i_flags; |
344 | 12.4k | p_pic->i_pts = p_sys->i_interpolated_pts; |
345 | 12.4k | p_pic->i_dts = p_sys->i_interpolated_dts; |
346 | | |
347 | | #if 0 |
348 | | msg_Err( p_dec, "output dts/pts (%"PRId64",%"PRId64")", p_pic->i_dts, p_pic->i_pts ); |
349 | | #endif |
350 | | /* Reset context */ |
351 | 12.4k | p_sys->p_frame = NULL; |
352 | 12.4k | p_sys->pp_last = &p_sys->p_frame; |
353 | 12.4k | } |
354 | | |
355 | 279k | return p_pic; |
356 | 412k | } |
357 | | |
358 | | /* ParseVOL: */ |
359 | | static int ParseVOL( decoder_t *p_dec, es_format_t *fmt, |
360 | | uint8_t *p_vol, int i_vol ) |
361 | 107k | { |
362 | 107k | decoder_sys_t *p_sys = p_dec->p_sys; |
363 | 107k | int i_vo_ver_id, i_shape; |
364 | 107k | h26x_aspect_ratio_t ar; |
365 | 107k | bs_t s; |
366 | | |
367 | 107k | for( ;; ) |
368 | 156k | { |
369 | 156k | if( i_vol <= 5 ) |
370 | 1.49k | return VLC_EGENERIC; |
371 | | |
372 | 155k | uint32_t i_startcode = GetDWBE( p_vol ); |
373 | 155k | if( i_startcode >= VIDEO_OBJECT_LAYER_START_CODE && |
374 | 148k | i_startcode < RESERVED_START_CODE ) |
375 | 105k | break; |
376 | | |
377 | 49.2k | p_vol++; i_vol--; |
378 | 49.2k | } |
379 | | |
380 | 105k | bs_init( &s, &p_vol[4], i_vol - 4 ); |
381 | | |
382 | 105k | bs_skip( &s, 1 ); /* random access */ |
383 | 105k | bs_skip( &s, 8 ); /* vo_type */ |
384 | 105k | if( bs_read1( &s ) ) |
385 | 72.2k | { |
386 | 72.2k | i_vo_ver_id = bs_read( &s, 4 ); |
387 | 72.2k | bs_skip( &s, 3 ); |
388 | 72.2k | } |
389 | 33.6k | else |
390 | 33.6k | { |
391 | 33.6k | i_vo_ver_id = 1; |
392 | 33.6k | } |
393 | 105k | ar.aspect_ratio_idc = bs_read( &s, 4 ) & 0xf; |
394 | 105k | if( ar.aspect_ratio_idc == 0xf ) |
395 | 30.6k | { |
396 | 30.6k | ar.aspect_ratio_idc = 0xff; // was only coded on 4 bits in MPEG4 |
397 | 30.6k | ar.sar_width = bs_read( &s, 8 ); |
398 | 30.6k | ar.sar_height = bs_read( &s, 8 ); |
399 | 30.6k | } |
400 | 105k | if(!p_dec->fmt_in->video.i_sar_num || |
401 | 6.96k | !p_dec->fmt_in->video.i_sar_den) |
402 | 99.7k | { |
403 | 99.7k | h26x_get_aspect_ratio(&ar, |
404 | 99.7k | &fmt->video.i_sar_num, |
405 | 99.7k | &fmt->video.i_sar_den); |
406 | 99.7k | } |
407 | | |
408 | 105k | if( bs_read1( &s ) ) |
409 | 59.2k | { |
410 | | /* vol control parameter */ |
411 | 59.2k | bs_skip( &s, 2 ); /* chroma_format */ |
412 | 59.2k | bs_skip( &s, 1 ); /* low_delay */ |
413 | | |
414 | 59.2k | if( bs_read1( &s ) ) |
415 | 30.7k | { |
416 | 30.7k | bs_skip( &s, 16 ); |
417 | 30.7k | bs_skip( &s, 16 ); |
418 | 30.7k | bs_skip( &s, 16 ); |
419 | 30.7k | bs_skip( &s, 3 ); |
420 | 30.7k | bs_skip( &s, 11 ); |
421 | 30.7k | bs_skip( &s, 1 ); |
422 | 30.7k | bs_skip( &s, 16 ); |
423 | 30.7k | } |
424 | 59.2k | } |
425 | | /* shape 0->RECT, 1->BIN, 2->BIN_ONLY, 3->GRAY */ |
426 | 105k | i_shape = bs_read( &s, 2 ); |
427 | 105k | if( i_shape == 3 && i_vo_ver_id != 1 ) |
428 | 18.6k | { |
429 | 18.6k | bs_skip( &s, 4 ); |
430 | 18.6k | } |
431 | | |
432 | 105k | if( !bs_read1( &s ) ) return VLC_EGENERIC; /* Marker */ |
433 | | |
434 | 40.7k | p_sys->i_fps_num = bs_read( &s, 16 ); /* Time increment resolution*/ |
435 | 40.7k | if( !p_sys->i_fps_num ) p_sys->i_fps_num = 1; |
436 | | |
437 | 40.7k | if( !bs_read1( &s ) ) return VLC_EGENERIC; /* Marker */ |
438 | | |
439 | 30.2k | if( bs_read1( &s ) ) |
440 | 28.8k | { |
441 | 28.8k | int i_time_increment_bits = vlc_log2( p_sys->i_fps_num - 1 ) + 1; |
442 | | |
443 | 28.8k | if( i_time_increment_bits < 1 ) i_time_increment_bits = 1; |
444 | | |
445 | 28.8k | p_sys->i_fps_den = bs_read( &s, i_time_increment_bits ); |
446 | 28.8k | } |
447 | 30.2k | if( i_shape == 0 ) |
448 | 8.67k | { |
449 | 8.67k | bs_skip( &s, 1 ); |
450 | 8.67k | fmt->video.i_width = bs_read( &s, 13 ); |
451 | 8.67k | bs_skip( &s, 1 ); |
452 | 8.67k | fmt->video.i_height= bs_read( &s, 13 ); |
453 | 8.67k | bs_skip( &s, 1 ); |
454 | 8.67k | } |
455 | | |
456 | 30.2k | return VLC_SUCCESS; |
457 | 40.7k | } |
458 | | |
459 | | static int ParseVO( decoder_t *p_dec, block_t *p_vo ) |
460 | 7.83k | { |
461 | 7.83k | bs_t s; |
462 | 7.83k | bs_init( &s, &p_vo->p_buffer[4], p_vo->i_buffer - 4 ); |
463 | 7.83k | if( bs_read1( &s ) ) |
464 | 2.05k | bs_skip( &s, 7 ); |
465 | | |
466 | 7.83k | const uint8_t visual_object_type = bs_read( &s, 4 ); |
467 | 7.83k | if( visual_object_type == 1 /* video ID */ || |
468 | 7.71k | visual_object_type == 2 /* still texture ID */ ) |
469 | 2.66k | { |
470 | 2.66k | h26x_colour_description_t colour = |
471 | 2.66k | { |
472 | 2.66k | .colour_primaries = 1, |
473 | 2.66k | .transfer_characteristics = 1, |
474 | 2.66k | .matrix_coeffs = 1, |
475 | 2.66k | .full_range_flag = 0, |
476 | 2.66k | }; |
477 | 2.66k | if( bs_read1( &s ) ) /* video_signal_type */ |
478 | 1.78k | { |
479 | 1.78k | bs_skip( &s, 3 ); |
480 | 1.78k | colour.full_range_flag = bs_read( &s, 1 ); |
481 | 1.78k | if( bs_read( &s, 1 ) ) /* colour description */ |
482 | 1.29k | { |
483 | 1.29k | colour.colour_primaries = bs_read( &s, 8 ); |
484 | 1.29k | colour.transfer_characteristics = bs_read( &s, 8 ); |
485 | 1.29k | colour.matrix_coeffs = bs_read( &s, 8 ); |
486 | 1.29k | } |
487 | 1.78k | } |
488 | | |
489 | 2.66k | if( p_dec->fmt_in->video.primaries == COLOR_PRIMARIES_UNDEF ) |
490 | 2.66k | { |
491 | 2.66k | h26x_get_colorimetry( &colour, |
492 | 2.66k | &p_dec->fmt_out.video.primaries, |
493 | 2.66k | &p_dec->fmt_out.video.transfer, |
494 | 2.66k | &p_dec->fmt_out.video.space, |
495 | 2.66k | &p_dec->fmt_out.video.color_range ); |
496 | 2.66k | } |
497 | 2.66k | } |
498 | | |
499 | 7.83k | return VLC_SUCCESS; |
500 | 7.83k | } |
501 | | |
502 | | static int ParseVOP( decoder_t *p_dec, block_t *p_vop ) |
503 | 15.0k | { |
504 | 15.0k | decoder_sys_t *p_sys = p_dec->p_sys; |
505 | 15.0k | int64_t i_time_increment, i_time_ref; |
506 | 15.0k | int i_modulo_time_base = 0, i_time_increment_bits; |
507 | 15.0k | bs_t s; |
508 | | |
509 | 15.0k | bs_init( &s, &p_vop->p_buffer[4], p_vop->i_buffer - 4 ); |
510 | | |
511 | 15.0k | switch( bs_read( &s, 2 ) ) |
512 | 15.0k | { |
513 | 6.00k | case 0: |
514 | 6.00k | p_sys->i_flags = BLOCK_FLAG_TYPE_I; |
515 | 6.00k | break; |
516 | 1.79k | case 1: |
517 | 1.79k | p_sys->i_flags = BLOCK_FLAG_TYPE_P; |
518 | 1.79k | break; |
519 | 3.36k | case 2: |
520 | 3.36k | p_sys->i_flags = BLOCK_FLAG_TYPE_B; |
521 | 3.36k | p_sys->b_frame = true; |
522 | 3.36k | break; |
523 | 3.84k | case 3: /* gni ? */ |
524 | 3.84k | p_sys->i_flags = BLOCK_FLAG_TYPE_PB; |
525 | 3.84k | break; |
526 | 15.0k | } |
527 | | |
528 | 411k | while( bs_read( &s, 1 ) ) i_modulo_time_base++; |
529 | 15.0k | if( !bs_read1( &s ) ) return VLC_EGENERIC; /* Marker */ |
530 | | |
531 | | /* VOP time increment */ |
532 | 12.4k | i_time_increment_bits = vlc_log2(p_sys->i_fps_num - 1) + 1; |
533 | 12.4k | if( i_time_increment_bits < 1 ) i_time_increment_bits = 1; |
534 | 12.4k | i_time_increment = bs_read( &s, i_time_increment_bits ); |
535 | | |
536 | | /* Interpolate PTS/DTS */ |
537 | 12.4k | if( !(p_sys->i_flags & BLOCK_FLAG_TYPE_B) ) |
538 | 9.80k | { |
539 | 9.80k | p_sys->i_last_time_ref = p_sys->i_time_ref; |
540 | 9.80k | p_sys->i_time_ref += |
541 | 9.80k | (i_modulo_time_base * p_sys->i_fps_num); |
542 | 9.80k | i_time_ref = p_sys->i_time_ref; |
543 | 9.80k | } |
544 | 2.59k | else |
545 | 2.59k | { |
546 | 2.59k | i_time_ref = p_sys->i_last_time_ref + |
547 | 2.59k | (i_modulo_time_base * p_sys->i_fps_num); |
548 | 2.59k | } |
549 | | |
550 | 12.4k | int64_t i_time_diff = (i_time_ref + i_time_increment) - (p_sys->i_last_time + p_sys->i_last_timeincr); |
551 | 12.4k | if( p_sys->i_fps_num && i_modulo_time_base == 0 && i_time_diff < 0 && -i_time_diff > p_sys->i_fps_num ) |
552 | 1.44k | { |
553 | 1.44k | msg_Warn(p_dec, "missing modulo_time_base update"); |
554 | 1.44k | i_modulo_time_base += -i_time_diff / p_sys->i_fps_num; |
555 | 1.44k | p_sys->i_time_ref += (i_modulo_time_base * p_sys->i_fps_num); |
556 | 1.44k | p_sys->i_time_ref += p_sys->i_last_timeincr % p_sys->i_fps_num; |
557 | 1.44k | i_time_ref = p_sys->i_time_ref; |
558 | 1.44k | } |
559 | | |
560 | 12.4k | if( p_sys->i_fps_num < 5 && /* Work-around buggy streams */ |
561 | 2.46k | p_dec->fmt_in->video.i_frame_rate > 0 && |
562 | 25 | p_dec->fmt_in->video.i_frame_rate_base > 0 ) |
563 | 25 | { |
564 | 25 | p_sys->i_interpolated_pts += vlc_tick_from_samples( |
565 | 25 | p_dec->fmt_in->video.i_frame_rate_base, |
566 | 25 | p_dec->fmt_in->video.i_frame_rate); |
567 | 25 | } |
568 | 12.3k | else if( p_sys->i_fps_num ) |
569 | 11.4k | { |
570 | 11.4k | i_time_diff = (i_time_ref + i_time_increment) - (p_sys->i_last_time + p_sys->i_last_timeincr); |
571 | 11.4k | p_sys->i_interpolated_pts += vlc_tick_from_samples( i_time_diff, p_sys->i_fps_num ); |
572 | 11.4k | } |
573 | | |
574 | | #if 0 |
575 | | msg_Err( p_dec, "interp dts/pts (%"PRId64",%"PRId64"), dts/pts (%"PRId64",%"PRId64") %"PRId64" mod %d inc %"PRId64, |
576 | | p_sys->i_interpolated_dts, p_sys->i_interpolated_pts, |
577 | | p_vop->i_dts, p_vop->i_pts, p_sys->i_time_ref, i_modulo_time_base, i_time_increment ); |
578 | | #endif |
579 | | |
580 | 12.4k | p_sys->i_last_time = i_time_ref; |
581 | 12.4k | p_sys->i_last_timeincr = i_time_increment; |
582 | | |
583 | | /* Correct interpolated dts when we receive a new pts/dts */ |
584 | 12.4k | if( p_vop->i_pts != VLC_TICK_INVALID ) |
585 | 323 | p_sys->i_interpolated_pts = p_vop->i_pts; |
586 | 12.4k | if( p_vop->i_dts != VLC_TICK_INVALID ) |
587 | 9.23k | p_sys->i_interpolated_dts = p_vop->i_dts; |
588 | | |
589 | 12.4k | if( (p_sys->i_flags & BLOCK_FLAG_TYPE_B) || !p_sys->b_frame ) |
590 | 5.48k | { |
591 | | /* Trivial case (DTS == PTS) */ |
592 | | |
593 | 5.48k | p_sys->i_interpolated_dts = p_sys->i_interpolated_pts; |
594 | | |
595 | 5.48k | if( p_vop->i_pts != VLC_TICK_INVALID ) |
596 | 319 | p_sys->i_interpolated_dts = p_vop->i_pts; |
597 | 5.48k | if( p_vop->i_dts != VLC_TICK_INVALID ) |
598 | 2.90k | p_sys->i_interpolated_dts = p_vop->i_dts; |
599 | | |
600 | 5.48k | p_sys->i_interpolated_pts = p_sys->i_interpolated_dts; |
601 | 5.48k | } |
602 | 6.92k | else |
603 | 6.92k | { |
604 | 6.92k | if( p_sys->i_last_ref_pts != VLC_TICK_INVALID ) |
605 | 6.44k | p_sys->i_interpolated_dts = p_sys->i_last_ref_pts; |
606 | | |
607 | 6.92k | p_sys->i_last_ref_pts = p_sys->i_interpolated_pts; |
608 | 6.92k | } |
609 | | |
610 | 12.4k | return VLC_SUCCESS; |
611 | 15.0k | } |
612 | | |
613 | | /* look at libavutil av_log2 ;) */ |
614 | | static int vlc_log2( unsigned int v ) |
615 | 41.2k | { |
616 | 41.2k | int n = 0; |
617 | 41.2k | static const int vlc_log2_table[16] = |
618 | 41.2k | { |
619 | 41.2k | 0,0,1,1,2,2,2,2, 3,3,3,3,3,3,3,3 |
620 | 41.2k | }; |
621 | | |
622 | 41.2k | if( v&0xffff0000 ) |
623 | 983 | { |
624 | 983 | v >>= 16; |
625 | 983 | n += 16; |
626 | 983 | } |
627 | 41.2k | if( v&0xff00 ) |
628 | 37.4k | { |
629 | 37.4k | v >>= 8; |
630 | 37.4k | n += 8; |
631 | 37.4k | } |
632 | 41.2k | if( v&0xf0 ) |
633 | 36.8k | { |
634 | 36.8k | v >>= 4; |
635 | 36.8k | n += 4; |
636 | 36.8k | } |
637 | 41.2k | n += vlc_log2_table[v]; |
638 | | |
639 | 41.2k | return n; |
640 | 41.2k | } |