/src/vlc/modules/packetizer/vc1.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * vc1.c |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2001, 2002, 2006 VLC authors and VideoLAN |
5 | | * |
6 | | * Authors: Laurent Aimar <fenrir@via.ecp.fr> |
7 | | * Gildas Bazin <gbazin@videolan.org> |
8 | | * |
9 | | * This program is free software; you can redistribute it and/or modify it |
10 | | * under the terms of the GNU Lesser General Public License as published by |
11 | | * the Free Software Foundation; either version 2.1 of the License, or |
12 | | * (at your option) any later version. |
13 | | * |
14 | | * This program is distributed in the hope that it will be useful, |
15 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | * GNU Lesser General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU Lesser General Public License |
20 | | * along with this program; if not, write to the Free Software Foundation, |
21 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
22 | | *****************************************************************************/ |
23 | | |
24 | | /***************************************************************************** |
25 | | * Preamble |
26 | | *****************************************************************************/ |
27 | | |
28 | | #ifdef HAVE_CONFIG_H |
29 | | # include "config.h" |
30 | | #endif |
31 | | |
32 | | #include <vlc_common.h> |
33 | | #include <vlc_plugin.h> |
34 | | #include <vlc_codec.h> |
35 | | #include <vlc_block.h> |
36 | | |
37 | | #include <vlc_bits.h> |
38 | | #include <vlc_block_helper.h> |
39 | | #include "../codec/cc.h" |
40 | | #include "packetizer_helper.h" |
41 | | #include "hxxx_nal.h" |
42 | | #include "hxxx_ep3b.h" |
43 | | #include "startcode_helper.h" |
44 | | #include "iso_color_tables.h" |
45 | | |
46 | | /***************************************************************************** |
47 | | * Module descriptor |
48 | | *****************************************************************************/ |
49 | | static int Open ( vlc_object_t * ); |
50 | | static void Close( vlc_object_t * ); |
51 | | |
52 | 150 | vlc_module_begin () |
53 | 75 | set_subcategory( SUBCAT_SOUT_PACKETIZER ) |
54 | 75 | set_description( N_("VC-1 packetizer") ) |
55 | 75 | set_capability( "video packetizer", 50 ) |
56 | 150 | set_callbacks( Open, Close ) |
57 | 75 | vlc_module_end () |
58 | | |
59 | | /***************************************************************************** |
60 | | * Local prototypes |
61 | | *****************************************************************************/ |
62 | | typedef struct |
63 | | { |
64 | | /* |
65 | | * Input properties |
66 | | */ |
67 | | packetizer_t packetizer; |
68 | | |
69 | | /* Current sequence header */ |
70 | | bool b_sequence_header; |
71 | | struct |
72 | | { |
73 | | block_t *p_sh; |
74 | | bool b_advanced_profile; |
75 | | bool b_interlaced; |
76 | | bool b_frame_interpolation; |
77 | | bool b_range_reduction; |
78 | | bool b_has_bframe; |
79 | | } sh; |
80 | | bool b_entry_point; |
81 | | struct |
82 | | { |
83 | | block_t *p_ep; |
84 | | } ep; |
85 | | |
86 | | /* */ |
87 | | bool b_frame; |
88 | | |
89 | | /* Current frame being built */ |
90 | | vlc_tick_t i_frame_dts; |
91 | | vlc_tick_t i_frame_pts; |
92 | | block_t *p_frame; |
93 | | block_t **pp_last; |
94 | | date_t dts; |
95 | | |
96 | | |
97 | | bool b_check_startcode; |
98 | | |
99 | | /* */ |
100 | | uint32_t i_cc_flags; |
101 | | vlc_tick_t i_cc_pts; |
102 | | vlc_tick_t i_cc_dts; |
103 | | cc_data_t cc; |
104 | | |
105 | | cc_data_t cc_next; |
106 | | } decoder_sys_t; |
107 | | |
108 | | typedef enum |
109 | | { |
110 | | IDU_TYPE_SEQUENCE_HEADER = 0x0f, |
111 | | IDU_TYPE_ENTRY_POINT = 0x0e, |
112 | | IDU_TYPE_FRAME = 0x0D, |
113 | | IDU_TYPE_FIELD = 0x0C, |
114 | | IDU_TYPE_SLICE = 0x0B, |
115 | | IDU_TYPE_END_OF_SEQUENCE = 0x0A, |
116 | | |
117 | | IDU_TYPE_SEQUENCE_LEVEL_USER_DATA = 0x1F, |
118 | | IDU_TYPE_ENTRY_POINT_USER_DATA = 0x1E, |
119 | | IDU_TYPE_FRAME_USER_DATA = 0x1D, |
120 | | IDU_TYPE_FIELD_USER_DATA = 0x1C, |
121 | | IDU_TYPE_SLICE_USER_DATA = 0x1B, |
122 | | } idu_type_t; |
123 | | |
124 | | static block_t *Packetize( decoder_t *p_dec, block_t **pp_block ); |
125 | | static void Flush( decoder_t * ); |
126 | | |
127 | | static void PacketizeReset( void *p_private, bool b_broken ); |
128 | | static int PacketizeValidate( void *p_private, block_t * ); |
129 | | static block_t *PacketizeDrain( void *p_private ); |
130 | | |
131 | | static block_t *OutputFrame( decoder_t *p_dec ); |
132 | | static block_t *ParseIDU( void *, bool *pb_ts_used, block_t *p_frag ); |
133 | | static block_t *GetCc( decoder_t *p_dec, decoder_cc_desc_t * ); |
134 | | |
135 | | static const uint8_t p_vc1_startcode[3] = { 0x00, 0x00, 0x01 }; |
136 | | /***************************************************************************** |
137 | | * Open: probe the packetizer and return score |
138 | | ***************************************************************************** |
139 | | * Tries to launch a decoder and return score so that the interface is able |
140 | | * to choose. |
141 | | *****************************************************************************/ |
142 | | static int Open( vlc_object_t *p_this ) |
143 | 19.2k | { |
144 | 19.2k | decoder_t *p_dec = (decoder_t*)p_this; |
145 | 19.2k | decoder_sys_t *p_sys; |
146 | | |
147 | 19.2k | if( p_dec->fmt_in->i_codec != VLC_CODEC_VC1 ) |
148 | 19.1k | return VLC_EGENERIC; |
149 | | |
150 | 99 | p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) ); |
151 | 99 | if( unlikely( !p_sys ) ) |
152 | 0 | return VLC_ENOMEM; |
153 | | |
154 | | /* Create the output format */ |
155 | 99 | es_format_Copy( &p_dec->fmt_out, p_dec->fmt_in ); |
156 | 99 | p_dec->pf_packetize = Packetize; |
157 | 99 | p_dec->pf_flush = Flush; |
158 | 99 | p_dec->pf_get_cc = GetCc; |
159 | | |
160 | 99 | packetizer_Init( &p_sys->packetizer, |
161 | 99 | p_vc1_startcode, sizeof(p_vc1_startcode), startcode_FindAnnexB, |
162 | 99 | NULL, 0, 4, |
163 | 99 | PacketizeReset, ParseIDU, PacketizeValidate, PacketizeDrain, |
164 | 99 | p_dec ); |
165 | | |
166 | 99 | p_sys->b_sequence_header = false; |
167 | 99 | p_sys->sh.p_sh = NULL; |
168 | 99 | p_sys->b_entry_point = false; |
169 | 99 | p_sys->ep.p_ep = NULL; |
170 | | |
171 | 99 | p_sys->i_frame_dts = VLC_TICK_INVALID; |
172 | 99 | p_sys->i_frame_pts = VLC_TICK_INVALID; |
173 | | |
174 | 99 | p_sys->b_frame = false; |
175 | 99 | p_sys->p_frame = NULL; |
176 | 99 | p_sys->pp_last = &p_sys->p_frame; |
177 | | |
178 | 99 | if( p_dec->fmt_in->video.i_frame_rate && p_dec->fmt_in->video.i_frame_rate_base ) |
179 | 0 | date_Init( &p_sys->dts, p_dec->fmt_in->video.i_frame_rate * 2, |
180 | 0 | p_dec->fmt_in->video.i_frame_rate_base ); |
181 | 99 | else |
182 | 99 | date_Init( &p_sys->dts, 30000*2, 1000 ); |
183 | 99 | p_sys->b_check_startcode = p_dec->fmt_in->b_packetized; |
184 | | |
185 | 99 | if( p_dec->fmt_out.i_extra > 0 ) |
186 | 0 | { |
187 | 0 | uint8_t *p_extra = p_dec->fmt_out.p_extra; |
188 | | |
189 | | /* With (some) ASF the first byte has to be stripped */ |
190 | 0 | if( p_extra[0] != 0x00 ) |
191 | 0 | { |
192 | 0 | memmove( &p_extra[0], &p_extra[1], p_dec->fmt_out.i_extra - 1 ); |
193 | 0 | p_dec->fmt_out.i_extra--; |
194 | 0 | } |
195 | | |
196 | | /* */ |
197 | 0 | if( p_dec->fmt_out.i_extra > 0 ) |
198 | 0 | packetizer_Header( &p_sys->packetizer, |
199 | 0 | p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); |
200 | 0 | } |
201 | | |
202 | | /* */ |
203 | 99 | p_sys->i_cc_pts = VLC_TICK_INVALID; |
204 | 99 | p_sys->i_cc_dts = VLC_TICK_INVALID; |
205 | 99 | p_sys->i_cc_flags = 0; |
206 | 99 | cc_Init( &p_sys->cc ); |
207 | 99 | cc_Init( &p_sys->cc_next ); |
208 | | |
209 | 99 | return VLC_SUCCESS; |
210 | 99 | } |
211 | | |
212 | | /***************************************************************************** |
213 | | * Close: |
214 | | *****************************************************************************/ |
215 | | static void Close( vlc_object_t *p_this ) |
216 | 99 | { |
217 | 99 | decoder_t *p_dec = (decoder_t*)p_this; |
218 | 99 | decoder_sys_t *p_sys = p_dec->p_sys; |
219 | | |
220 | 99 | packetizer_Clean( &p_sys->packetizer ); |
221 | 99 | if( p_sys->p_frame ) |
222 | 52 | block_Release( p_sys->p_frame ); |
223 | 99 | if( p_sys->sh.p_sh ) |
224 | 78 | block_Release( p_sys->sh.p_sh ); |
225 | 99 | if( p_sys->ep.p_ep ) |
226 | 63 | block_Release( p_sys->ep.p_ep ); |
227 | | |
228 | 99 | cc_Exit( &p_sys->cc_next ); |
229 | 99 | cc_Exit( &p_sys->cc ); |
230 | | |
231 | 99 | free( p_sys ); |
232 | 99 | } |
233 | | |
234 | | /***************************************************************************** |
235 | | * Packetize: packetize an access unit |
236 | | *****************************************************************************/ |
237 | | static block_t *Packetize( decoder_t *p_dec, block_t **pp_block ) |
238 | 38.4k | { |
239 | 38.4k | decoder_sys_t *p_sys = p_dec->p_sys; |
240 | | |
241 | 38.4k | if( p_sys->b_check_startcode && pp_block && *pp_block ) |
242 | 21.3k | { |
243 | | /* Fix syntax for (some?) VC1 from asf */ |
244 | 21.3k | const unsigned i_startcode = sizeof(p_vc1_startcode); |
245 | | |
246 | 21.3k | block_t *p_block = *pp_block; |
247 | 21.3k | if( p_block->i_buffer > 0 && |
248 | 21.3k | ( p_block->i_buffer < i_startcode || |
249 | 21.3k | memcmp( p_block->p_buffer, p_vc1_startcode, i_startcode ) ) ) |
250 | 20.9k | { |
251 | 20.9k | *pp_block = p_block = block_Realloc( p_block, i_startcode+1, p_block->i_buffer ); |
252 | 20.9k | if( p_block ) |
253 | 20.9k | { |
254 | 20.9k | memcpy( p_block->p_buffer, p_vc1_startcode, i_startcode ); |
255 | | |
256 | 20.9k | if( p_sys->b_sequence_header && p_sys->sh.b_interlaced && |
257 | 7.80k | p_block->i_buffer > i_startcode+1 && |
258 | 7.80k | (p_block->p_buffer[i_startcode+1] & 0xc0) == 0xc0 ) |
259 | 1.07k | p_block->p_buffer[i_startcode] = IDU_TYPE_FIELD; |
260 | 19.8k | else |
261 | 19.8k | p_block->p_buffer[i_startcode] = IDU_TYPE_FRAME; |
262 | 20.9k | } |
263 | 20.9k | } |
264 | 21.3k | p_sys->b_check_startcode = false; |
265 | 21.3k | } |
266 | | |
267 | 38.4k | block_t *p_au = packetizer_Packetize( &p_sys->packetizer, pp_block ); |
268 | 38.4k | if( !p_au ) |
269 | 21.6k | p_sys->b_check_startcode = p_dec->fmt_in->b_packetized; |
270 | | |
271 | 38.4k | return p_au; |
272 | 38.4k | } |
273 | | |
274 | | static void Flush( decoder_t *p_dec ) |
275 | 0 | { |
276 | 0 | decoder_sys_t *p_sys = p_dec->p_sys; |
277 | |
|
278 | 0 | packetizer_Flush( &p_sys->packetizer ); |
279 | 0 | } |
280 | | |
281 | | static void PacketizeReset( void *p_private, bool b_flush ) |
282 | 17 | { |
283 | 17 | decoder_t *p_dec = p_private; |
284 | 17 | decoder_sys_t *p_sys = p_dec->p_sys; |
285 | | |
286 | 17 | if( b_flush ) |
287 | 0 | { |
288 | 0 | if( p_sys->p_frame ) |
289 | 0 | block_ChainRelease( p_sys->p_frame ); |
290 | 0 | p_sys->p_frame = NULL; |
291 | 0 | p_sys->pp_last = &p_sys->p_frame; |
292 | 0 | p_sys->b_frame = false; |
293 | 0 | } |
294 | | |
295 | 17 | p_sys->i_frame_dts = VLC_TICK_INVALID; |
296 | 17 | p_sys->i_frame_pts = VLC_TICK_INVALID; |
297 | 17 | date_Set( &p_sys->dts, VLC_TICK_INVALID ); |
298 | 17 | } |
299 | | |
300 | | static int PacketizeValidate( void *p_private, block_t *p_au ) |
301 | 16.7k | { |
302 | 16.7k | decoder_t *p_dec = p_private; |
303 | 16.7k | decoder_sys_t *p_sys = p_dec->p_sys; |
304 | | |
305 | 16.7k | if( date_Get( &p_sys->dts ) == VLC_TICK_INVALID ) |
306 | 0 | { |
307 | 0 | msg_Dbg( p_dec, "need a starting pts/dts" ); |
308 | 0 | return VLC_EGENERIC; |
309 | 0 | } |
310 | 16.7k | VLC_UNUSED(p_au); |
311 | 16.7k | return VLC_SUCCESS; |
312 | 16.7k | } |
313 | | |
314 | | static block_t * PacketizeDrain( void *p_private ) |
315 | 102 | { |
316 | 102 | decoder_t *p_dec = p_private; |
317 | 102 | decoder_sys_t *p_sys = p_dec->p_sys; |
318 | 102 | return p_sys->b_frame ? OutputFrame( p_dec ) : NULL; |
319 | 102 | } |
320 | | |
321 | | /* BuildExtraData: gather sequence header and entry point */ |
322 | | static void BuildExtraData( decoder_t *p_dec ) |
323 | 10.5k | { |
324 | 10.5k | decoder_sys_t *p_sys = p_dec->p_sys; |
325 | 10.5k | es_format_t *p_es = &p_dec->fmt_out; |
326 | 10.5k | size_t i_extra; |
327 | 10.5k | if( !p_sys->b_sequence_header || !p_sys->b_entry_point ) |
328 | 78 | return; |
329 | | |
330 | 10.4k | i_extra = p_sys->sh.p_sh->i_buffer + p_sys->ep.p_ep->i_buffer; |
331 | 10.4k | if( p_es->i_extra != i_extra ) |
332 | 6.10k | { |
333 | 6.10k | p_es->i_extra = i_extra; |
334 | 6.10k | p_es->p_extra = xrealloc( p_es->p_extra, p_es->i_extra ); |
335 | 6.10k | } |
336 | 10.4k | memcpy( p_es->p_extra, |
337 | 10.4k | p_sys->sh.p_sh->p_buffer, p_sys->sh.p_sh->i_buffer ); |
338 | 10.4k | memcpy( (uint8_t*)p_es->p_extra + p_sys->sh.p_sh->i_buffer, |
339 | 10.4k | p_sys->ep.p_ep->p_buffer, p_sys->ep.p_ep->i_buffer ); |
340 | 10.4k | } |
341 | | |
342 | | static block_t *OutputFrame( decoder_t *p_dec ) |
343 | 16.7k | { |
344 | 16.7k | decoder_sys_t *p_sys = p_dec->p_sys; |
345 | 16.7k | const int i_pic_flags = p_sys->p_frame->i_flags; |
346 | | |
347 | | /* Prepend SH and EP on I */ |
348 | 16.7k | if( i_pic_flags & BLOCK_FLAG_TYPE_I ) |
349 | 1.06k | { |
350 | 1.06k | block_t *p_list = block_Duplicate( p_sys->sh.p_sh ); |
351 | 1.06k | block_t *p_ep = block_Duplicate( p_sys->ep.p_ep ); |
352 | 1.06k | if( p_ep ) |
353 | 1.06k | block_ChainAppend( &p_list, p_ep ); |
354 | 1.06k | block_ChainAppend( &p_list, p_sys->p_frame ); |
355 | 1.06k | p_list->i_flags = i_pic_flags; |
356 | 1.06k | p_sys->p_frame = p_list; |
357 | 1.06k | } |
358 | | |
359 | 16.7k | vlc_tick_t i_dts = p_sys->i_frame_dts; |
360 | 16.7k | vlc_tick_t i_pts = p_sys->i_frame_pts; |
361 | | |
362 | | /* */ |
363 | 16.7k | block_t *p_pic = block_ChainGather( p_sys->p_frame ); |
364 | 16.7k | if( p_pic ) |
365 | 16.7k | { |
366 | 16.7k | p_pic->i_dts = p_sys->i_frame_dts; |
367 | 16.7k | p_pic->i_pts = p_sys->i_frame_pts; |
368 | 16.7k | } |
369 | | |
370 | | /* */ |
371 | 16.7k | if( i_dts == VLC_TICK_INVALID ) |
372 | 443 | i_dts = date_Get( &p_sys->dts ); |
373 | 16.3k | else |
374 | 16.3k | date_Set( &p_sys->dts, i_dts ); |
375 | | |
376 | 16.7k | if( i_pts == VLC_TICK_INVALID ) |
377 | 452 | { |
378 | 452 | if( !p_sys->sh.b_has_bframe || (i_pic_flags & BLOCK_FLAG_TYPE_B ) ) |
379 | 1 | i_pts = i_dts; |
380 | | /* TODO compute pts for other case */ |
381 | 452 | } |
382 | | |
383 | 16.7k | if( p_pic ) |
384 | 16.7k | { |
385 | 16.7k | p_pic->i_dts = i_dts; |
386 | 16.7k | p_pic->i_pts = i_pts; |
387 | 16.7k | } |
388 | | |
389 | | //msg_Dbg( p_dec, "-------------- dts=%"PRId64" pts=%"PRId64, i_dts, i_pts ); |
390 | | |
391 | | /* We can interpolate dts/pts only if we have a frame rate */ |
392 | 16.7k | if( p_dec->fmt_out.video.i_frame_rate && p_dec->fmt_out.video.i_frame_rate_base ) |
393 | 73 | { |
394 | 73 | date_Increment( &p_sys->dts, 2 ); |
395 | | // msg_Dbg( p_dec, "-------------- XXX0 dts=%"PRId64" pts=%"PRId64" interpolated=%"PRId64, |
396 | | // i_dts, i_pts, date_Get( &p_sys->dts ) ); |
397 | 73 | } |
398 | | |
399 | | /* CC */ |
400 | 16.7k | p_sys->i_cc_pts = i_pts; |
401 | 16.7k | p_sys->i_cc_dts = i_dts; |
402 | 16.7k | p_sys->i_cc_flags = i_pic_flags; |
403 | | |
404 | 16.7k | p_sys->cc = p_sys->cc_next; |
405 | 16.7k | cc_Flush( &p_sys->cc_next ); |
406 | | |
407 | | /* Reset context */ |
408 | 16.7k | p_sys->b_frame = false; |
409 | 16.7k | p_sys->i_frame_dts = VLC_TICK_INVALID; |
410 | 16.7k | p_sys->i_frame_pts = VLC_TICK_INVALID; |
411 | 16.7k | p_sys->p_frame = NULL; |
412 | 16.7k | p_sys->pp_last = &p_sys->p_frame; |
413 | | |
414 | 16.7k | return p_pic; |
415 | 16.7k | } |
416 | | |
417 | | /* ParseIDU: parse an Independent Decoding Unit */ |
418 | | static block_t *ParseIDU( void *p_private, bool *pb_ts_used, block_t *p_frag ) |
419 | 138k | { |
420 | 138k | decoder_t *p_dec = p_private; |
421 | 138k | decoder_sys_t *p_sys = p_dec->p_sys; |
422 | 138k | block_t *p_pic = NULL; |
423 | 138k | const idu_type_t idu = p_frag->p_buffer[3]; |
424 | | |
425 | 138k | *pb_ts_used = false; |
426 | 138k | if( !p_sys->b_sequence_header && idu != IDU_TYPE_SEQUENCE_HEADER ) |
427 | 6.95k | { |
428 | 6.95k | msg_Warn( p_dec, "waiting for sequence header" ); |
429 | 6.95k | block_Release( p_frag ); |
430 | 6.95k | return NULL; |
431 | 6.95k | } |
432 | 131k | if( p_sys->b_sequence_header && !p_sys->b_entry_point && idu != IDU_TYPE_ENTRY_POINT ) |
433 | 2.03k | { |
434 | 2.03k | msg_Warn( p_dec, "waiting for entry point" ); |
435 | 2.03k | block_Release( p_frag ); |
436 | 2.03k | return NULL; |
437 | 2.03k | } |
438 | | /* TODO we do not gather ENTRY_POINT and SEQUENCE_DATA user data |
439 | | * But It should not be a problem for decoder */ |
440 | | |
441 | | /* Do we have completed a frame */ |
442 | 129k | if( p_sys->b_frame && |
443 | 17.7k | idu != IDU_TYPE_FRAME_USER_DATA && |
444 | 17.7k | idu != IDU_TYPE_FIELD && idu != IDU_TYPE_FIELD_USER_DATA && |
445 | 16.7k | idu != IDU_TYPE_SLICE && idu != IDU_TYPE_SLICE_USER_DATA && |
446 | 16.7k | idu != IDU_TYPE_END_OF_SEQUENCE ) |
447 | 16.7k | { |
448 | 16.7k | p_pic = OutputFrame( p_dec ); |
449 | 16.7k | } |
450 | | |
451 | | /* */ |
452 | 129k | if( p_sys->i_frame_dts == VLC_TICK_INVALID && p_sys->i_frame_pts == VLC_TICK_INVALID ) |
453 | 41.3k | { |
454 | 41.3k | p_sys->i_frame_dts = p_frag->i_dts; |
455 | 41.3k | p_sys->i_frame_pts = p_frag->i_pts; |
456 | 41.3k | *pb_ts_used = true; |
457 | 41.3k | } |
458 | | |
459 | | /* We will add back SH and EP on I frames */ |
460 | 129k | block_t *p_release = NULL; |
461 | 129k | if( idu != IDU_TYPE_SEQUENCE_HEADER && idu != IDU_TYPE_ENTRY_POINT ) |
462 | 118k | block_ChainLastAppend( &p_sys->pp_last, p_frag ); |
463 | 10.5k | else |
464 | 10.5k | p_release = p_frag; |
465 | | |
466 | | /* Parse IDU */ |
467 | 129k | if( idu == IDU_TYPE_SEQUENCE_HEADER ) |
468 | 7.18k | { |
469 | 7.18k | es_format_t *p_es = &p_dec->fmt_out; |
470 | 7.18k | bs_t s; |
471 | | |
472 | | /* */ |
473 | 7.18k | if( p_sys->sh.p_sh ) |
474 | 7.10k | block_Release( p_sys->sh.p_sh ); |
475 | 7.18k | p_sys->sh.p_sh = block_Duplicate( p_frag ); |
476 | | |
477 | | /* Auto detect VC-1_SPMP_PESpacket_PayloadFormatHeader (SMPTE RP 227) for simple/main profile |
478 | | * TODO find a test case and valid it */ |
479 | 7.18k | if( p_frag->i_buffer > 8 && (p_frag->p_buffer[4]&0x80) == 0 ) /* for advanced profile, the first bit is 1 */ |
480 | 347 | { |
481 | 347 | const video_format_t *p_v = &p_dec->fmt_in->video; |
482 | 347 | const size_t i_potential_width = GetWBE( &p_frag->p_buffer[4] ); |
483 | 347 | const size_t i_potential_height = GetWBE( &p_frag->p_buffer[6] ); |
484 | | |
485 | 347 | if( i_potential_width >= 2 && i_potential_width <= 8192 && |
486 | 216 | i_potential_height >= 2 && i_potential_height <= 8192 ) |
487 | 46 | { |
488 | 46 | if( ( p_v->i_width <= 0 && p_v->i_height <= 0 ) || |
489 | 41 | ( p_v->i_width == i_potential_width && p_v->i_height == i_potential_height ) ) |
490 | 5 | { |
491 | 5 | static const uint8_t startcode[4] = { 0x00, 0x00, 0x01, IDU_TYPE_SEQUENCE_HEADER }; |
492 | 5 | p_es->video.i_width = i_potential_width; |
493 | 5 | p_es->video.i_height = i_potential_height; |
494 | | |
495 | | /* Remove it */ |
496 | 5 | p_frag->p_buffer += 4; |
497 | 5 | p_frag->i_buffer -= 4; |
498 | 5 | memcpy( p_frag->p_buffer, startcode, sizeof(startcode) ); |
499 | 5 | } |
500 | 46 | } |
501 | 347 | } |
502 | | |
503 | | /* Parse it */ |
504 | 7.18k | struct hxxx_bsfw_ep3b_ctx_s bsctx; |
505 | 7.18k | hxxx_bsfw_ep3b_ctx_init( &bsctx ); |
506 | 7.18k | bs_init_custom( &s, &p_frag->p_buffer[4], p_frag->i_buffer - 4, |
507 | 7.18k | &hxxx_bsfw_ep3b_callbacks, &bsctx ); |
508 | | |
509 | 7.18k | p_dec->fmt_out.i_profile = bs_read( &s, 2 ); |
510 | 7.18k | if( p_dec->fmt_out.i_profile == 3 ) |
511 | 6.66k | { |
512 | 6.66k | p_dec->fmt_out.i_level = bs_read( &s, 3 ); |
513 | | |
514 | | /* Advanced profile */ |
515 | 6.66k | p_sys->sh.b_advanced_profile = true; |
516 | 6.66k | p_sys->sh.b_range_reduction = false; |
517 | 6.66k | p_sys->sh.b_has_bframe = true; |
518 | | |
519 | 6.66k | bs_skip( &s, 2+3+5+1 ); // chroma format + frame rate Q + bit rate Q + postprocflag |
520 | | |
521 | 6.66k | p_es->video.i_width = 2*bs_read( &s, 12 )+2; |
522 | 6.66k | p_es->video.i_height = 2*bs_read( &s, 12 )+2; |
523 | | |
524 | 6.66k | if( !p_sys->b_sequence_header ) |
525 | 6.66k | msg_Dbg( p_dec, "found sequence header for advanced profile level L%d resolution %dx%d", |
526 | 6.66k | p_dec->fmt_out.i_level, p_es->video.i_width, p_es->video.i_height); |
527 | | |
528 | 6.66k | bs_skip( &s, 1 );// pulldown |
529 | 6.66k | p_sys->sh.b_interlaced = bs_read( &s, 1 ); |
530 | 6.66k | bs_skip( &s, 1 );// frame counter |
531 | 6.66k | p_sys->sh.b_frame_interpolation = bs_read( &s, 1 ); |
532 | 6.66k | bs_skip( &s, 1 ); // Reserved |
533 | 6.66k | bs_skip( &s, 1 ); // Psf |
534 | | |
535 | 6.66k | if( bs_read( &s, 1 ) ) /* Display extension */ |
536 | 2.95k | { |
537 | 2.95k | const int i_display_width = bs_read( &s, 14 )+1; |
538 | 2.95k | const int i_display_height = bs_read( &s, 14 )+1; |
539 | | |
540 | 2.95k | p_es->video.i_sar_num = i_display_width * p_es->video.i_height; |
541 | 2.95k | p_es->video.i_sar_den = i_display_height * p_es->video.i_width; |
542 | | |
543 | 2.95k | if( !p_sys->b_sequence_header ) |
544 | 2.95k | msg_Dbg( p_dec, "display size %dx%d", i_display_width, i_display_height ); |
545 | | |
546 | 2.95k | if( bs_read( &s, 1 ) ) /* Pixel aspect ratio (PAR/SAR) */ |
547 | 2.54k | { |
548 | 2.54k | static const unsigned p_ar[16][2] = { |
549 | 2.54k | { 0, 0}, { 1, 1}, {12,11}, {10,11}, {16,11}, {40,33}, |
550 | 2.54k | {24,11}, {20,11}, {32,11}, {80,33}, {18,11}, {15,11}, |
551 | 2.54k | {64,33}, {160,99},{ 0, 0}, { 0, 0} |
552 | 2.54k | }; |
553 | 2.54k | int i_ar = bs_read( &s, 4 ); |
554 | 2.54k | unsigned i_ar_w, i_ar_h; |
555 | | |
556 | 2.54k | if( i_ar == 15 ) |
557 | 188 | { |
558 | 188 | i_ar_w = bs_read( &s, 8 ); |
559 | 188 | i_ar_h = bs_read( &s, 8 ); |
560 | 188 | } |
561 | 2.35k | else |
562 | 2.35k | { |
563 | 2.35k | i_ar_w = p_ar[i_ar][0]; |
564 | 2.35k | i_ar_h = p_ar[i_ar][1]; |
565 | 2.35k | } |
566 | 2.54k | vlc_ureduce( &i_ar_w, &i_ar_h, i_ar_w, i_ar_h, 0 ); |
567 | 2.54k | if( !p_sys->b_sequence_header ) |
568 | 2.54k | msg_Dbg( p_dec, "aspect ratio %d:%d", i_ar_w, i_ar_h ); |
569 | 2.54k | } |
570 | 2.95k | } |
571 | 6.66k | if( bs_read( &s, 1 ) ) /* Frame rate */ |
572 | 3.97k | { |
573 | 3.97k | unsigned i_fps_num = 0; |
574 | 3.97k | unsigned i_fps_den = 0; |
575 | 3.97k | if( bs_read( &s, 1 ) ) |
576 | 1.59k | { |
577 | 1.59k | i_fps_num = bs_read( &s, 16 )+1; |
578 | 1.59k | i_fps_den = 32; |
579 | 1.59k | } |
580 | 2.38k | else |
581 | 2.38k | { |
582 | 2.38k | const int i_nr = bs_read( &s, 8 ); |
583 | 2.38k | const int i_dn = bs_read( &s, 4 ); |
584 | | |
585 | 2.38k | switch( i_nr ) |
586 | 2.38k | { |
587 | 0 | case 1: i_fps_num = 24000; break; |
588 | 0 | case 2: i_fps_num = 25000; break; |
589 | 749 | case 3: i_fps_num = 30000; break; |
590 | 535 | case 4: i_fps_num = 50000; break; |
591 | 0 | case 5: i_fps_num = 60000; break; |
592 | 3 | case 6: i_fps_num = 48000; break; |
593 | 11 | case 7: i_fps_num = 72000; break; |
594 | 2.38k | } |
595 | 2.38k | switch( i_dn ) |
596 | 2.38k | { |
597 | 0 | case 1: i_fps_den = 1000; break; |
598 | 294 | case 2: i_fps_den = 1001; break; |
599 | 2.38k | } |
600 | 2.38k | } |
601 | | |
602 | 3.97k | if( i_fps_num != 0 && i_fps_den != 0 && |
603 | 1.88k | (p_dec->fmt_in->video.i_frame_rate == 0 || |
604 | 0 | p_dec->fmt_in->video.i_frame_rate_base == 0) ) |
605 | 1.88k | { |
606 | 1.88k | vlc_ureduce( &p_es->video.i_frame_rate, &p_es->video.i_frame_rate_base, i_fps_num, i_fps_den, 0 ); |
607 | | |
608 | 1.88k | if( !p_sys->b_sequence_header ) |
609 | 5 | { |
610 | 5 | msg_Dbg( p_dec, "frame rate %d/%d", p_es->video.i_frame_rate, p_es->video.i_frame_rate_base ); |
611 | 5 | date_Change( &p_sys->dts, p_es->video.i_frame_rate * 2, p_es->video.i_frame_rate_base ); |
612 | 5 | } |
613 | 1.88k | } |
614 | 3.97k | } |
615 | 6.66k | if( bs_read1( &s ) && /* Color Format */ |
616 | 3.41k | p_dec->fmt_in->video.primaries == COLOR_PRIMARIES_UNDEF ) |
617 | 3.41k | { |
618 | 3.41k | p_es->video.primaries = iso_23001_8_cp_to_vlc_primaries( bs_read( &s, 8 ) ); |
619 | 3.41k | p_es->video.transfer = iso_23001_8_tc_to_vlc_xfer( bs_read( &s, 8 ) ); |
620 | 3.41k | p_es->video.space = iso_23001_8_mc_to_vlc_coeffs( bs_read( &s, 8 ) ); |
621 | 3.41k | } |
622 | 6.66k | } |
623 | 515 | else |
624 | 515 | { |
625 | | /* Simple and main profile */ |
626 | 515 | p_sys->sh.b_advanced_profile = false; |
627 | 515 | p_sys->sh.b_interlaced = false; |
628 | | |
629 | 515 | if( !p_sys->b_sequence_header ) |
630 | 515 | msg_Dbg( p_dec, "found sequence header for %s profile", p_dec->fmt_out.i_profile == 0 ? "simple" : "main" ); |
631 | | |
632 | 515 | bs_skip( &s, 2+3+5+1+1+ // reserved + frame rate Q + bit rate Q + loop filter + reserved |
633 | 515 | 1+1+1+1+2+ // multiresolution + reserved + fast uv mc + extended mv + dquant |
634 | 515 | 1+1+1+1 ); // variable size transform + reserved + overlap + sync marker |
635 | 515 | p_sys->sh.b_range_reduction = bs_read( &s, 1 ); |
636 | 515 | if( bs_read( &s, 3 ) > 0 ) |
637 | 137 | p_sys->sh.b_has_bframe = true; |
638 | 378 | else |
639 | 378 | p_sys->sh.b_has_bframe = false; |
640 | 515 | bs_skip( &s, 2 ); // quantizer |
641 | | |
642 | 515 | p_sys->sh.b_frame_interpolation = bs_read( &s, 1 ); |
643 | 515 | } |
644 | 7.18k | p_sys->b_sequence_header = true; |
645 | 7.18k | BuildExtraData( p_dec ); |
646 | 7.18k | } |
647 | 122k | else if( idu == IDU_TYPE_ENTRY_POINT ) |
648 | 3.33k | { |
649 | 3.33k | if( p_sys->ep.p_ep ) |
650 | 3.27k | block_Release( p_sys->ep.p_ep ); |
651 | 3.33k | p_sys->ep.p_ep = block_Duplicate( p_frag ); |
652 | | |
653 | 3.33k | if( !p_sys->b_entry_point ) |
654 | 3.33k | msg_Dbg( p_dec, "found entry point" ); |
655 | | |
656 | 3.33k | p_sys->b_entry_point = true; |
657 | 3.33k | BuildExtraData( p_dec ); |
658 | 3.33k | } |
659 | 118k | else if( idu == IDU_TYPE_FRAME ) |
660 | 16.7k | { |
661 | 16.7k | bs_t s; |
662 | | |
663 | | /* Parse it + interpolate pts/dts if possible */ |
664 | 16.7k | struct hxxx_bsfw_ep3b_ctx_s bsctx; |
665 | 16.7k | hxxx_bsfw_ep3b_ctx_init( &bsctx ); |
666 | 16.7k | bs_init_custom( &s, &p_frag->p_buffer[4], p_frag->i_buffer - 4, |
667 | 16.7k | &hxxx_bsfw_ep3b_callbacks, &bsctx ); |
668 | | |
669 | 16.7k | if( p_sys->sh.b_advanced_profile ) |
670 | 16.7k | { |
671 | 16.7k | int i_fcm = 0; |
672 | | |
673 | 16.7k | if( p_sys->sh.b_interlaced ) |
674 | 6.73k | { |
675 | 6.73k | if( bs_read( &s, 1 ) ) |
676 | 1.12k | { |
677 | 1.12k | if( bs_read( &s, 1 ) ) |
678 | 0 | i_fcm = 1; /* interlaced field */ |
679 | 1.12k | else |
680 | 1.12k | i_fcm = 2; /* interlaced frame */ |
681 | 1.12k | } |
682 | 6.73k | } |
683 | | |
684 | 16.7k | if( i_fcm == 1 ) /*interlaced field */ |
685 | 0 | { |
686 | | /* XXX for mixed I/P we should check reference usage before marking them I (too much work) */ |
687 | 0 | switch( bs_read( &s, 3 ) ) |
688 | 0 | { |
689 | 0 | case 0: /* II */ |
690 | 0 | case 1: /* IP */ |
691 | 0 | case 2: /* PI */ |
692 | 0 | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I; |
693 | 0 | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I; |
694 | 0 | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I; |
695 | 0 | break; |
696 | 0 | case 3: /* PP */ |
697 | 0 | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P; |
698 | 0 | break; |
699 | 0 | case 4: /* BB */ |
700 | 0 | case 5: /* BBi */ |
701 | 0 | case 6: /* BiB */ |
702 | 0 | case 7: /* BiBi */ |
703 | 0 | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B; |
704 | 0 | break; |
705 | 0 | } |
706 | 0 | } |
707 | 16.7k | else |
708 | 16.7k | { |
709 | 16.7k | if( !bs_read( &s, 1 ) ) |
710 | 13.1k | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P; |
711 | 3.57k | else if( !bs_read( &s, 1 ) ) |
712 | 1.62k | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B; |
713 | 1.94k | else if( !bs_read( &s, 1 ) ) |
714 | 1.06k | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I; |
715 | 885 | else if( !bs_read( &s, 1 ) ) |
716 | 390 | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B; /* Bi */ |
717 | 495 | else |
718 | 495 | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P; /* P Skip */ |
719 | 16.7k | } |
720 | 16.7k | } |
721 | 3 | else |
722 | 3 | { |
723 | 3 | if( p_sys->sh.b_frame_interpolation ) |
724 | 0 | bs_skip( &s, 1 ); // interpolate |
725 | 3 | bs_skip( &s, 2 ); // frame count |
726 | 3 | if( p_sys->sh.b_range_reduction ) |
727 | 1 | bs_skip( &s, 1 ); // range reduction |
728 | | |
729 | 3 | if( bs_read( &s, 1 ) ) |
730 | 0 | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P; |
731 | 3 | else if( !p_sys->sh.b_has_bframe || bs_read( &s, 1 ) ) |
732 | 3 | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I; |
733 | 0 | else |
734 | 0 | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B; |
735 | 3 | } |
736 | 16.7k | p_sys->b_frame = true; |
737 | 16.7k | } |
738 | 102k | else if( idu == IDU_TYPE_FRAME_USER_DATA ) |
739 | 2.48k | { |
740 | 2.48k | bs_t s; |
741 | 2.48k | const size_t i_size = p_frag->i_buffer - 4; |
742 | 2.48k | struct hxxx_bsfw_ep3b_ctx_s bsctx; |
743 | 2.48k | hxxx_bsfw_ep3b_ctx_init( &bsctx ); |
744 | 2.48k | bs_init_custom( &s, &p_frag->p_buffer[4], i_size, &hxxx_bsfw_ep3b_callbacks, &bsctx ); |
745 | | |
746 | 2.48k | unsigned i_data; |
747 | 2.48k | uint8_t *p_data = malloc( i_size ); |
748 | 2.48k | if( p_data ) |
749 | 2.48k | { |
750 | | /* store converted data */ |
751 | 778k | for( i_data = 0; i_data + 1 /* trailing 0x80 flush byte */<i_size; i_data++ ) |
752 | 775k | { |
753 | 775k | p_data[i_data] = bs_read( &s, 8 ); |
754 | 775k | if( bs_error(&s) ) |
755 | 28 | break; |
756 | 775k | } |
757 | | |
758 | | /* TS 101 154 Auxiliary Data and VC-1 video */ |
759 | 2.48k | static const uint8_t p_DVB1_user_identifier[] = { |
760 | 2.48k | 0x47, 0x41, 0x39, 0x34 /* user identifier */ |
761 | 2.48k | }; |
762 | | |
763 | | /* Check if we have DVB1_data() */ |
764 | 2.48k | if( i_data >= sizeof(p_DVB1_user_identifier) && |
765 | 2.47k | !memcmp( p_data, p_DVB1_user_identifier, sizeof(p_DVB1_user_identifier) ) ) |
766 | 971 | { |
767 | 971 | cc_ProbeAndExtract( &p_sys->cc_next, true, p_data, i_data ); |
768 | 971 | } |
769 | | |
770 | 2.48k | free( p_data ); |
771 | 2.48k | } |
772 | 2.48k | } |
773 | | |
774 | 129k | if( p_release ) |
775 | 10.5k | block_Release( p_release ); |
776 | 129k | return p_pic; |
777 | 129k | } |
778 | | |
779 | | /***************************************************************************** |
780 | | * GetCc: |
781 | | *****************************************************************************/ |
782 | | static block_t *GetCc( decoder_t *p_dec, decoder_cc_desc_t *p_desc ) |
783 | 16.7k | { |
784 | 16.7k | decoder_sys_t *p_sys = p_dec->p_sys; |
785 | 16.7k | block_t *p_cc; |
786 | | |
787 | 16.7k | p_cc = block_Alloc( p_sys->cc.i_data); |
788 | 16.7k | if( p_cc ) |
789 | 16.7k | { |
790 | 16.7k | memcpy( p_cc->p_buffer, p_sys->cc.p_data, p_sys->cc.i_data ); |
791 | 16.7k | p_cc->i_dts = |
792 | 16.7k | p_cc->i_pts = p_sys->cc.b_reorder ? p_sys->i_cc_pts : p_sys->i_cc_dts; |
793 | 16.7k | p_cc->i_flags = p_sys->i_cc_flags & BLOCK_FLAG_TYPE_MASK; |
794 | | |
795 | 16.7k | p_desc->i_608_channels = p_sys->cc.i_608channels; |
796 | 16.7k | p_desc->i_708_channels = p_sys->cc.i_708channels; |
797 | 16.7k | p_desc->i_reorder_depth = p_sys->cc.b_reorder ? 4 : -1; |
798 | 16.7k | } |
799 | 16.7k | cc_Flush( &p_sys->cc ); |
800 | 16.7k | return p_cc; |
801 | 16.7k | } |