/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 | 170 | vlc_module_begin () |
53 | 85 | set_subcategory( SUBCAT_SOUT_PACKETIZER ) |
54 | 85 | set_description( N_("VC-1 packetizer") ) |
55 | 85 | set_capability( "video packetizer", 50 ) |
56 | 170 | set_callbacks( Open, Close ) |
57 | 85 | 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 | 14.8k | { |
144 | 14.8k | decoder_t *p_dec = (decoder_t*)p_this; |
145 | 14.8k | decoder_sys_t *p_sys; |
146 | | |
147 | 14.8k | if( p_dec->fmt_in->i_codec != VLC_CODEC_VC1 ) |
148 | 9.52k | return VLC_EGENERIC; |
149 | | |
150 | 5.29k | p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) ); |
151 | 5.29k | if( unlikely( !p_sys ) ) |
152 | 0 | return VLC_ENOMEM; |
153 | | |
154 | | /* Create the output format */ |
155 | 5.29k | es_format_Copy( &p_dec->fmt_out, p_dec->fmt_in ); |
156 | 5.29k | p_dec->pf_packetize = Packetize; |
157 | 5.29k | p_dec->pf_flush = Flush; |
158 | 5.29k | p_dec->pf_get_cc = GetCc; |
159 | | |
160 | 5.29k | packetizer_Init( &p_sys->packetizer, |
161 | 5.29k | p_vc1_startcode, sizeof(p_vc1_startcode), startcode_FindAnnexB, |
162 | 5.29k | NULL, 0, 4, |
163 | 5.29k | PacketizeReset, ParseIDU, PacketizeValidate, PacketizeDrain, |
164 | 5.29k | p_dec ); |
165 | | |
166 | 5.29k | p_sys->b_sequence_header = false; |
167 | 5.29k | p_sys->sh.p_sh = NULL; |
168 | 5.29k | p_sys->b_entry_point = false; |
169 | 5.29k | p_sys->ep.p_ep = NULL; |
170 | | |
171 | 5.29k | p_sys->i_frame_dts = VLC_TICK_INVALID; |
172 | 5.29k | p_sys->i_frame_pts = VLC_TICK_INVALID; |
173 | | |
174 | 5.29k | p_sys->b_frame = false; |
175 | 5.29k | p_sys->p_frame = NULL; |
176 | 5.29k | p_sys->pp_last = &p_sys->p_frame; |
177 | | |
178 | 5.29k | if( p_dec->fmt_in->video.i_frame_rate && p_dec->fmt_in->video.i_frame_rate_base ) |
179 | 423 | date_Init( &p_sys->dts, p_dec->fmt_in->video.i_frame_rate * 2, |
180 | 423 | p_dec->fmt_in->video.i_frame_rate_base ); |
181 | 4.86k | else |
182 | 4.86k | date_Init( &p_sys->dts, 30000*2, 1000 ); |
183 | 5.29k | p_sys->b_check_startcode = p_dec->fmt_in->b_packetized; |
184 | | |
185 | 5.29k | if( p_dec->fmt_out.i_extra > 0 ) |
186 | 2.05k | { |
187 | 2.05k | uint8_t *p_extra = p_dec->fmt_out.p_extra; |
188 | | |
189 | | /* With (some) ASF the first byte has to be stripped */ |
190 | 2.05k | 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 | 2.05k | if( p_dec->fmt_out.i_extra > 0 ) |
198 | 2.05k | packetizer_Header( &p_sys->packetizer, |
199 | 2.05k | p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); |
200 | 2.05k | } |
201 | | |
202 | | /* */ |
203 | 5.29k | p_sys->i_cc_pts = VLC_TICK_INVALID; |
204 | 5.29k | p_sys->i_cc_dts = VLC_TICK_INVALID; |
205 | 5.29k | p_sys->i_cc_flags = 0; |
206 | 5.29k | cc_Init( &p_sys->cc ); |
207 | 5.29k | cc_Init( &p_sys->cc_next ); |
208 | | |
209 | 5.29k | return VLC_SUCCESS; |
210 | 5.29k | } |
211 | | |
212 | | /***************************************************************************** |
213 | | * Close: |
214 | | *****************************************************************************/ |
215 | | static void Close( vlc_object_t *p_this ) |
216 | 5.29k | { |
217 | 5.29k | decoder_t *p_dec = (decoder_t*)p_this; |
218 | 5.29k | decoder_sys_t *p_sys = p_dec->p_sys; |
219 | | |
220 | 5.29k | packetizer_Clean( &p_sys->packetizer ); |
221 | 5.29k | if( p_sys->p_frame ) |
222 | 1.08k | block_Release( p_sys->p_frame ); |
223 | 5.29k | if( p_sys->sh.p_sh ) |
224 | 4.99k | block_Release( p_sys->sh.p_sh ); |
225 | 5.29k | if( p_sys->ep.p_ep ) |
226 | 4.69k | block_Release( p_sys->ep.p_ep ); |
227 | | |
228 | 5.29k | cc_Exit( &p_sys->cc_next ); |
229 | 5.29k | cc_Exit( &p_sys->cc ); |
230 | | |
231 | 5.29k | free( p_sys ); |
232 | 5.29k | } |
233 | | |
234 | | /***************************************************************************** |
235 | | * Packetize: packetize an access unit |
236 | | *****************************************************************************/ |
237 | | static block_t *Packetize( decoder_t *p_dec, block_t **pp_block ) |
238 | 974k | { |
239 | 974k | decoder_sys_t *p_sys = p_dec->p_sys; |
240 | | |
241 | 974k | if( p_sys->b_check_startcode && pp_block && *pp_block ) |
242 | 193k | { |
243 | | /* Fix syntax for (some?) VC1 from asf */ |
244 | 193k | const unsigned i_startcode = sizeof(p_vc1_startcode); |
245 | | |
246 | 193k | block_t *p_block = *pp_block; |
247 | 193k | if( p_block->i_buffer > 0 && |
248 | 193k | ( p_block->i_buffer < i_startcode || |
249 | 193k | memcmp( p_block->p_buffer, p_vc1_startcode, i_startcode ) ) ) |
250 | 29 | { |
251 | 29 | *pp_block = p_block = block_Realloc( p_block, i_startcode+1, p_block->i_buffer ); |
252 | 29 | if( p_block ) |
253 | 29 | { |
254 | 29 | memcpy( p_block->p_buffer, p_vc1_startcode, i_startcode ); |
255 | | |
256 | 29 | if( p_sys->b_sequence_header && p_sys->sh.b_interlaced && |
257 | 0 | p_block->i_buffer > i_startcode+1 && |
258 | 0 | (p_block->p_buffer[i_startcode+1] & 0xc0) == 0xc0 ) |
259 | 0 | p_block->p_buffer[i_startcode] = IDU_TYPE_FIELD; |
260 | 29 | else |
261 | 29 | p_block->p_buffer[i_startcode] = IDU_TYPE_FRAME; |
262 | 29 | } |
263 | 29 | } |
264 | 193k | p_sys->b_check_startcode = false; |
265 | 193k | } |
266 | | |
267 | 974k | block_t *p_au = packetizer_Packetize( &p_sys->packetizer, pp_block ); |
268 | 974k | if( !p_au ) |
269 | 223k | p_sys->b_check_startcode = p_dec->fmt_in->b_packetized; |
270 | | |
271 | 974k | return p_au; |
272 | 974k | } |
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 | 731 | { |
283 | 731 | decoder_t *p_dec = p_private; |
284 | 731 | decoder_sys_t *p_sys = p_dec->p_sys; |
285 | | |
286 | 731 | 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 | 731 | p_sys->i_frame_dts = VLC_TICK_INVALID; |
296 | 731 | p_sys->i_frame_pts = VLC_TICK_INVALID; |
297 | 731 | date_Set( &p_sys->dts, VLC_TICK_INVALID ); |
298 | 731 | } |
299 | | |
300 | | static int PacketizeValidate( void *p_private, block_t *p_au ) |
301 | 755k | { |
302 | 755k | decoder_t *p_dec = p_private; |
303 | 755k | decoder_sys_t *p_sys = p_dec->p_sys; |
304 | | |
305 | 755k | if( date_Get( &p_sys->dts ) == VLC_TICK_INVALID ) |
306 | 5.17k | { |
307 | 5.17k | msg_Dbg( p_dec, "need a starting pts/dts" ); |
308 | 5.17k | return VLC_EGENERIC; |
309 | 5.17k | } |
310 | 750k | VLC_UNUSED(p_au); |
311 | 750k | return VLC_SUCCESS; |
312 | 755k | } |
313 | | |
314 | | static block_t * PacketizeDrain( void *p_private ) |
315 | 13.3k | { |
316 | 13.3k | decoder_t *p_dec = p_private; |
317 | 13.3k | decoder_sys_t *p_sys = p_dec->p_sys; |
318 | 13.3k | return p_sys->b_frame ? OutputFrame( p_dec ) : NULL; |
319 | 13.3k | } |
320 | | |
321 | | /* BuildExtraData: gather sequence header and entry point */ |
322 | | static void BuildExtraData( decoder_t *p_dec ) |
323 | 398k | { |
324 | 398k | decoder_sys_t *p_sys = p_dec->p_sys; |
325 | 398k | es_format_t *p_es = &p_dec->fmt_out; |
326 | 398k | size_t i_extra; |
327 | 398k | if( !p_sys->b_sequence_header || !p_sys->b_entry_point ) |
328 | 4.99k | return; |
329 | | |
330 | 393k | i_extra = p_sys->sh.p_sh->i_buffer + p_sys->ep.p_ep->i_buffer; |
331 | 393k | if( p_es->i_extra != i_extra ) |
332 | 221k | { |
333 | 221k | p_es->i_extra = i_extra; |
334 | 221k | p_es->p_extra = xrealloc( p_es->p_extra, p_es->i_extra ); |
335 | 221k | } |
336 | 393k | memcpy( p_es->p_extra, |
337 | 393k | p_sys->sh.p_sh->p_buffer, p_sys->sh.p_sh->i_buffer ); |
338 | 393k | memcpy( (uint8_t*)p_es->p_extra + p_sys->sh.p_sh->i_buffer, |
339 | 393k | p_sys->ep.p_ep->p_buffer, p_sys->ep.p_ep->i_buffer ); |
340 | 393k | } |
341 | | |
342 | | static block_t *OutputFrame( decoder_t *p_dec ) |
343 | 755k | { |
344 | 755k | decoder_sys_t *p_sys = p_dec->p_sys; |
345 | 755k | const int i_pic_flags = p_sys->p_frame->i_flags; |
346 | | |
347 | | /* Prepend SH and EP on I */ |
348 | 755k | if( i_pic_flags & BLOCK_FLAG_TYPE_I ) |
349 | 442k | { |
350 | 442k | block_t *p_list = block_Duplicate( p_sys->sh.p_sh ); |
351 | 442k | block_t *p_ep = block_Duplicate( p_sys->ep.p_ep ); |
352 | 442k | if( p_ep ) |
353 | 442k | block_ChainAppend( &p_list, p_ep ); |
354 | 442k | block_ChainAppend( &p_list, p_sys->p_frame ); |
355 | 442k | p_list->i_flags = i_pic_flags; |
356 | 442k | p_sys->p_frame = p_list; |
357 | 442k | } |
358 | | |
359 | 755k | vlc_tick_t i_dts = p_sys->i_frame_dts; |
360 | 755k | vlc_tick_t i_pts = p_sys->i_frame_pts; |
361 | | |
362 | | /* */ |
363 | 755k | block_t *p_pic = block_ChainGather( p_sys->p_frame ); |
364 | 755k | if( p_pic ) |
365 | 755k | { |
366 | 755k | p_pic->i_dts = p_sys->i_frame_dts; |
367 | 755k | p_pic->i_pts = p_sys->i_frame_pts; |
368 | 755k | } |
369 | | |
370 | | /* */ |
371 | 755k | if( i_dts == VLC_TICK_INVALID ) |
372 | 557k | i_dts = date_Get( &p_sys->dts ); |
373 | 198k | else |
374 | 198k | date_Set( &p_sys->dts, i_dts ); |
375 | | |
376 | 755k | if( i_pts == VLC_TICK_INVALID ) |
377 | 556k | { |
378 | 556k | if( !p_sys->sh.b_has_bframe || (i_pic_flags & BLOCK_FLAG_TYPE_B ) ) |
379 | 359k | i_pts = i_dts; |
380 | | /* TODO compute pts for other case */ |
381 | 556k | } |
382 | | |
383 | 755k | if( p_pic ) |
384 | 755k | { |
385 | 755k | p_pic->i_dts = i_dts; |
386 | 755k | p_pic->i_pts = i_pts; |
387 | 755k | } |
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 | 755k | if( p_dec->fmt_out.video.i_frame_rate && p_dec->fmt_out.video.i_frame_rate_base ) |
393 | 470k | { |
394 | 470k | 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 | 470k | } |
398 | | |
399 | | /* CC */ |
400 | 755k | p_sys->i_cc_pts = i_pts; |
401 | 755k | p_sys->i_cc_dts = i_dts; |
402 | 755k | p_sys->i_cc_flags = i_pic_flags; |
403 | | |
404 | 755k | p_sys->cc = p_sys->cc_next; |
405 | 755k | cc_Flush( &p_sys->cc_next ); |
406 | | |
407 | | /* Reset context */ |
408 | 755k | p_sys->b_frame = false; |
409 | 755k | p_sys->i_frame_dts = VLC_TICK_INVALID; |
410 | 755k | p_sys->i_frame_pts = VLC_TICK_INVALID; |
411 | 755k | p_sys->p_frame = NULL; |
412 | 755k | p_sys->pp_last = &p_sys->p_frame; |
413 | | |
414 | 755k | return p_pic; |
415 | 755k | } |
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 | 1.86M | { |
420 | 1.86M | decoder_t *p_dec = p_private; |
421 | 1.86M | decoder_sys_t *p_sys = p_dec->p_sys; |
422 | 1.86M | block_t *p_pic = NULL; |
423 | 1.86M | const idu_type_t idu = p_frag->p_buffer[3]; |
424 | | |
425 | 1.86M | *pb_ts_used = false; |
426 | 1.86M | if( !p_sys->b_sequence_header && idu != IDU_TYPE_SEQUENCE_HEADER ) |
427 | 39.5k | { |
428 | 39.5k | msg_Warn( p_dec, "waiting for sequence header" ); |
429 | 39.5k | block_Release( p_frag ); |
430 | 39.5k | return NULL; |
431 | 39.5k | } |
432 | 1.82M | if( p_sys->b_sequence_header && !p_sys->b_entry_point && idu != IDU_TYPE_ENTRY_POINT ) |
433 | 16.2k | { |
434 | 16.2k | msg_Warn( p_dec, "waiting for entry point" ); |
435 | 16.2k | block_Release( p_frag ); |
436 | 16.2k | return NULL; |
437 | 16.2k | } |
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 | 1.81M | if( p_sys->b_frame && |
443 | 871k | idu != IDU_TYPE_FRAME_USER_DATA && |
444 | 854k | idu != IDU_TYPE_FIELD && idu != IDU_TYPE_FIELD_USER_DATA && |
445 | 779k | idu != IDU_TYPE_SLICE && idu != IDU_TYPE_SLICE_USER_DATA && |
446 | 749k | idu != IDU_TYPE_END_OF_SEQUENCE ) |
447 | 749k | { |
448 | 749k | p_pic = OutputFrame( p_dec ); |
449 | 749k | } |
450 | | |
451 | | /* */ |
452 | 1.81M | if( p_sys->i_frame_dts == VLC_TICK_INVALID && p_sys->i_frame_pts == VLC_TICK_INVALID ) |
453 | 1.37M | { |
454 | 1.37M | p_sys->i_frame_dts = p_frag->i_dts; |
455 | 1.37M | p_sys->i_frame_pts = p_frag->i_pts; |
456 | 1.37M | *pb_ts_used = true; |
457 | 1.37M | } |
458 | | |
459 | | /* We will add back SH and EP on I frames */ |
460 | 1.81M | block_t *p_release = NULL; |
461 | 1.81M | if( idu != IDU_TYPE_SEQUENCE_HEADER && idu != IDU_TYPE_ENTRY_POINT ) |
462 | 1.41M | block_ChainLastAppend( &p_sys->pp_last, p_frag ); |
463 | 398k | else |
464 | 398k | p_release = p_frag; |
465 | | |
466 | | /* Parse IDU */ |
467 | 1.81M | if( idu == IDU_TYPE_SEQUENCE_HEADER ) |
468 | 167k | { |
469 | 167k | es_format_t *p_es = &p_dec->fmt_out; |
470 | 167k | bs_t s; |
471 | | |
472 | | /* */ |
473 | 167k | if( p_sys->sh.p_sh ) |
474 | 162k | block_Release( p_sys->sh.p_sh ); |
475 | 167k | 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 | 167k | if( p_frag->i_buffer > 8 && (p_frag->p_buffer[4]&0x80) == 0 ) /* for advanced profile, the first bit is 1 */ |
480 | 46.8k | { |
481 | 46.8k | const video_format_t *p_v = &p_dec->fmt_in->video; |
482 | 46.8k | const size_t i_potential_width = GetWBE( &p_frag->p_buffer[4] ); |
483 | 46.8k | const size_t i_potential_height = GetWBE( &p_frag->p_buffer[6] ); |
484 | | |
485 | 46.8k | if( i_potential_width >= 2 && i_potential_width <= 8192 && |
486 | 34.8k | i_potential_height >= 2 && i_potential_height <= 8192 ) |
487 | 22.4k | { |
488 | 22.4k | if( ( p_v->i_width <= 0 && p_v->i_height <= 0 ) || |
489 | 826 | ( p_v->i_width == i_potential_width && p_v->i_height == i_potential_height ) ) |
490 | 21.9k | { |
491 | 21.9k | static const uint8_t startcode[4] = { 0x00, 0x00, 0x01, IDU_TYPE_SEQUENCE_HEADER }; |
492 | 21.9k | p_es->video.i_width = i_potential_width; |
493 | 21.9k | p_es->video.i_height = i_potential_height; |
494 | | |
495 | | /* Remove it */ |
496 | 21.9k | p_frag->p_buffer += 4; |
497 | 21.9k | p_frag->i_buffer -= 4; |
498 | 21.9k | memcpy( p_frag->p_buffer, startcode, sizeof(startcode) ); |
499 | 21.9k | } |
500 | 22.4k | } |
501 | 46.8k | } |
502 | | |
503 | | /* Parse it */ |
504 | 167k | struct hxxx_bsfw_ep3b_ctx_s bsctx; |
505 | 167k | hxxx_bsfw_ep3b_ctx_init( &bsctx ); |
506 | 167k | bs_init_custom( &s, &p_frag->p_buffer[4], p_frag->i_buffer - 4, |
507 | 167k | &hxxx_bsfw_ep3b_callbacks, &bsctx ); |
508 | | |
509 | 167k | p_dec->fmt_out.i_profile = bs_read( &s, 2 ); |
510 | 167k | if( p_dec->fmt_out.i_profile == 3 ) |
511 | 130k | { |
512 | 130k | p_dec->fmt_out.i_level = bs_read( &s, 3 ); |
513 | | |
514 | | /* Advanced profile */ |
515 | 130k | p_sys->sh.b_advanced_profile = true; |
516 | 130k | p_sys->sh.b_range_reduction = false; |
517 | 130k | p_sys->sh.b_has_bframe = true; |
518 | | |
519 | 130k | bs_skip( &s, 2+3+5+1 ); // chroma format + frame rate Q + bit rate Q + postprocflag |
520 | | |
521 | 130k | p_es->video.i_width = 2*bs_read( &s, 12 )+2; |
522 | 130k | p_es->video.i_height = 2*bs_read( &s, 12 )+2; |
523 | | |
524 | 130k | if( !p_sys->b_sequence_header ) |
525 | 130k | msg_Dbg( p_dec, "found sequence header for advanced profile level L%d resolution %dx%d", |
526 | 130k | p_dec->fmt_out.i_level, p_es->video.i_width, p_es->video.i_height); |
527 | | |
528 | 130k | bs_skip( &s, 1 );// pulldown |
529 | 130k | p_sys->sh.b_interlaced = bs_read( &s, 1 ); |
530 | 130k | bs_skip( &s, 1 );// frame counter |
531 | 130k | p_sys->sh.b_frame_interpolation = bs_read( &s, 1 ); |
532 | 130k | bs_skip( &s, 1 ); // Reserved |
533 | 130k | bs_skip( &s, 1 ); // Psf |
534 | | |
535 | 130k | if( bs_read( &s, 1 ) ) /* Display extension */ |
536 | 36.0k | { |
537 | 36.0k | const int i_display_width = bs_read( &s, 14 )+1; |
538 | 36.0k | const int i_display_height = bs_read( &s, 14 )+1; |
539 | | |
540 | 36.0k | p_es->video.i_sar_num = i_display_width * p_es->video.i_height; |
541 | 36.0k | p_es->video.i_sar_den = i_display_height * p_es->video.i_width; |
542 | | |
543 | 36.0k | if( !p_sys->b_sequence_header ) |
544 | 36.0k | msg_Dbg( p_dec, "display size %dx%d", i_display_width, i_display_height ); |
545 | | |
546 | 36.0k | if( bs_read( &s, 1 ) ) /* Pixel aspect ratio (PAR/SAR) */ |
547 | 24.8k | { |
548 | 24.8k | static const unsigned p_ar[16][2] = { |
549 | 24.8k | { 0, 0}, { 1, 1}, {12,11}, {10,11}, {16,11}, {40,33}, |
550 | 24.8k | {24,11}, {20,11}, {32,11}, {80,33}, {18,11}, {15,11}, |
551 | 24.8k | {64,33}, {160,99},{ 0, 0}, { 0, 0} |
552 | 24.8k | }; |
553 | 24.8k | int i_ar = bs_read( &s, 4 ); |
554 | 24.8k | unsigned i_ar_w, i_ar_h; |
555 | | |
556 | 24.8k | if( i_ar == 15 ) |
557 | 8.02k | { |
558 | 8.02k | i_ar_w = bs_read( &s, 8 ); |
559 | 8.02k | i_ar_h = bs_read( &s, 8 ); |
560 | 8.02k | } |
561 | 16.8k | else |
562 | 16.8k | { |
563 | 16.8k | i_ar_w = p_ar[i_ar][0]; |
564 | 16.8k | i_ar_h = p_ar[i_ar][1]; |
565 | 16.8k | } |
566 | 24.8k | vlc_ureduce( &i_ar_w, &i_ar_h, i_ar_w, i_ar_h, 0 ); |
567 | 24.8k | if( !p_sys->b_sequence_header ) |
568 | 24.8k | msg_Dbg( p_dec, "aspect ratio %d:%d", i_ar_w, i_ar_h ); |
569 | 24.8k | } |
570 | 36.0k | } |
571 | 130k | if( bs_read( &s, 1 ) ) /* Frame rate */ |
572 | 27.7k | { |
573 | 27.7k | unsigned i_fps_num = 0; |
574 | 27.7k | unsigned i_fps_den = 0; |
575 | 27.7k | if( bs_read( &s, 1 ) ) |
576 | 16.8k | { |
577 | 16.8k | i_fps_num = bs_read( &s, 16 )+1; |
578 | 16.8k | i_fps_den = 32; |
579 | 16.8k | } |
580 | 10.8k | else |
581 | 10.8k | { |
582 | 10.8k | const int i_nr = bs_read( &s, 8 ); |
583 | 10.8k | const int i_dn = bs_read( &s, 4 ); |
584 | | |
585 | 10.8k | switch( i_nr ) |
586 | 10.8k | { |
587 | 229 | case 1: i_fps_num = 24000; break; |
588 | 2.38k | case 2: i_fps_num = 25000; break; |
589 | 907 | case 3: i_fps_num = 30000; break; |
590 | 2.33k | case 4: i_fps_num = 50000; break; |
591 | 13 | case 5: i_fps_num = 60000; break; |
592 | 18 | case 6: i_fps_num = 48000; break; |
593 | 177 | case 7: i_fps_num = 72000; break; |
594 | 10.8k | } |
595 | 10.8k | switch( i_dn ) |
596 | 10.8k | { |
597 | 571 | case 1: i_fps_den = 1000; break; |
598 | 304 | case 2: i_fps_den = 1001; break; |
599 | 10.8k | } |
600 | 10.8k | } |
601 | | |
602 | 27.7k | if( i_fps_num != 0 && i_fps_den != 0 && |
603 | 17.3k | (p_dec->fmt_in->video.i_frame_rate == 0 || |
604 | 4.41k | p_dec->fmt_in->video.i_frame_rate_base == 0) ) |
605 | 12.9k | { |
606 | 12.9k | vlc_ureduce( &p_es->video.i_frame_rate, &p_es->video.i_frame_rate_base, i_fps_num, i_fps_den, 0 ); |
607 | | |
608 | 12.9k | if( !p_sys->b_sequence_header ) |
609 | 381 | { |
610 | 381 | msg_Dbg( p_dec, "frame rate %d/%d", p_es->video.i_frame_rate, p_es->video.i_frame_rate_base ); |
611 | 381 | date_Change( &p_sys->dts, p_es->video.i_frame_rate * 2, p_es->video.i_frame_rate_base ); |
612 | 381 | } |
613 | 12.9k | } |
614 | 27.7k | } |
615 | 130k | if( bs_read1( &s ) && /* Color Format */ |
616 | 49.2k | p_dec->fmt_in->video.primaries == COLOR_PRIMARIES_UNDEF ) |
617 | 44.0k | { |
618 | 44.0k | p_es->video.primaries = iso_23001_8_cp_to_vlc_primaries( bs_read( &s, 8 ) ); |
619 | 44.0k | p_es->video.transfer = iso_23001_8_tc_to_vlc_xfer( bs_read( &s, 8 ) ); |
620 | 44.0k | p_es->video.space = iso_23001_8_mc_to_vlc_coeffs( bs_read( &s, 8 ) ); |
621 | 44.0k | } |
622 | 130k | } |
623 | 36.1k | else |
624 | 36.1k | { |
625 | | /* Simple and main profile */ |
626 | 36.1k | p_sys->sh.b_advanced_profile = false; |
627 | 36.1k | p_sys->sh.b_interlaced = false; |
628 | | |
629 | 36.1k | if( !p_sys->b_sequence_header ) |
630 | 36.1k | msg_Dbg( p_dec, "found sequence header for %s profile", p_dec->fmt_out.i_profile == 0 ? "simple" : "main" ); |
631 | | |
632 | 36.1k | bs_skip( &s, 2+3+5+1+1+ // reserved + frame rate Q + bit rate Q + loop filter + reserved |
633 | 36.1k | 1+1+1+1+2+ // multiresolution + reserved + fast uv mc + extended mv + dquant |
634 | 36.1k | 1+1+1+1 ); // variable size transform + reserved + overlap + sync marker |
635 | 36.1k | p_sys->sh.b_range_reduction = bs_read( &s, 1 ); |
636 | 36.1k | if( bs_read( &s, 3 ) > 0 ) |
637 | 2.73k | p_sys->sh.b_has_bframe = true; |
638 | 33.4k | else |
639 | 33.4k | p_sys->sh.b_has_bframe = false; |
640 | 36.1k | bs_skip( &s, 2 ); // quantizer |
641 | | |
642 | 36.1k | p_sys->sh.b_frame_interpolation = bs_read( &s, 1 ); |
643 | 36.1k | } |
644 | 167k | p_sys->b_sequence_header = true; |
645 | 167k | BuildExtraData( p_dec ); |
646 | 167k | } |
647 | 1.64M | else if( idu == IDU_TYPE_ENTRY_POINT ) |
648 | 231k | { |
649 | 231k | if( p_sys->ep.p_ep ) |
650 | 227k | block_Release( p_sys->ep.p_ep ); |
651 | 231k | p_sys->ep.p_ep = block_Duplicate( p_frag ); |
652 | | |
653 | 231k | if( !p_sys->b_entry_point ) |
654 | 231k | msg_Dbg( p_dec, "found entry point" ); |
655 | | |
656 | 231k | p_sys->b_entry_point = true; |
657 | 231k | BuildExtraData( p_dec ); |
658 | 231k | } |
659 | 1.41M | else if( idu == IDU_TYPE_FRAME ) |
660 | 755k | { |
661 | 755k | bs_t s; |
662 | | |
663 | | /* Parse it + interpolate pts/dts if possible */ |
664 | 755k | struct hxxx_bsfw_ep3b_ctx_s bsctx; |
665 | 755k | hxxx_bsfw_ep3b_ctx_init( &bsctx ); |
666 | 755k | bs_init_custom( &s, &p_frag->p_buffer[4], p_frag->i_buffer - 4, |
667 | 755k | &hxxx_bsfw_ep3b_callbacks, &bsctx ); |
668 | | |
669 | 755k | if( p_sys->sh.b_advanced_profile ) |
670 | 397k | { |
671 | 397k | int i_fcm = 0; |
672 | | |
673 | 397k | if( p_sys->sh.b_interlaced ) |
674 | 103k | { |
675 | 103k | if( bs_read( &s, 1 ) ) |
676 | 76.1k | { |
677 | 76.1k | if( bs_read( &s, 1 ) ) |
678 | 74.7k | i_fcm = 1; /* interlaced field */ |
679 | 1.42k | else |
680 | 1.42k | i_fcm = 2; /* interlaced frame */ |
681 | 76.1k | } |
682 | 103k | } |
683 | | |
684 | 397k | if( i_fcm == 1 ) /*interlaced field */ |
685 | 74.7k | { |
686 | | /* XXX for mixed I/P we should check reference usage before marking them I (too much work) */ |
687 | 74.7k | switch( bs_read( &s, 3 ) ) |
688 | 74.7k | { |
689 | 32.2k | case 0: /* II */ |
690 | 34.6k | case 1: /* IP */ |
691 | 47.4k | case 2: /* PI */ |
692 | 47.4k | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I; |
693 | 47.4k | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I; |
694 | 47.4k | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I; |
695 | 47.4k | break; |
696 | 728 | case 3: /* PP */ |
697 | 728 | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P; |
698 | 728 | break; |
699 | 311 | case 4: /* BB */ |
700 | 3.22k | case 5: /* BBi */ |
701 | 4.26k | case 6: /* BiB */ |
702 | 26.6k | case 7: /* BiBi */ |
703 | 26.6k | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B; |
704 | 26.6k | break; |
705 | 74.7k | } |
706 | 74.7k | } |
707 | 322k | else |
708 | 322k | { |
709 | 322k | if( !bs_read( &s, 1 ) ) |
710 | 226k | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P; |
711 | 95.8k | else if( !bs_read( &s, 1 ) ) |
712 | 5.08k | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B; |
713 | 90.7k | else if( !bs_read( &s, 1 ) ) |
714 | 49.8k | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I; |
715 | 40.8k | else if( !bs_read( &s, 1 ) ) |
716 | 9.29k | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B; /* Bi */ |
717 | 31.5k | else |
718 | 31.5k | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P; /* P Skip */ |
719 | 322k | } |
720 | 397k | } |
721 | 358k | else |
722 | 358k | { |
723 | 358k | if( p_sys->sh.b_frame_interpolation ) |
724 | 6.47k | bs_skip( &s, 1 ); // interpolate |
725 | 358k | bs_skip( &s, 2 ); // frame count |
726 | 358k | if( p_sys->sh.b_range_reduction ) |
727 | 6.36k | bs_skip( &s, 1 ); // range reduction |
728 | | |
729 | 358k | if( bs_read( &s, 1 ) ) |
730 | 8.20k | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P; |
731 | 350k | else if( !p_sys->sh.b_has_bframe || bs_read( &s, 1 ) ) |
732 | 344k | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I; |
733 | 5.88k | else |
734 | 5.88k | p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B; |
735 | 358k | } |
736 | 755k | p_sys->b_frame = true; |
737 | 755k | } |
738 | 657k | else if( idu == IDU_TYPE_FRAME_USER_DATA ) |
739 | 58.4k | { |
740 | 58.4k | bs_t s; |
741 | 58.4k | const size_t i_size = p_frag->i_buffer - 4; |
742 | 58.4k | struct hxxx_bsfw_ep3b_ctx_s bsctx; |
743 | 58.4k | hxxx_bsfw_ep3b_ctx_init( &bsctx ); |
744 | 58.4k | bs_init_custom( &s, &p_frag->p_buffer[4], i_size, &hxxx_bsfw_ep3b_callbacks, &bsctx ); |
745 | | |
746 | 58.4k | unsigned i_data; |
747 | 58.4k | uint8_t *p_data = malloc( i_size ); |
748 | 58.4k | if( p_data ) |
749 | 58.4k | { |
750 | | /* store converted data */ |
751 | 23.5M | for( i_data = 0; i_data + 1 /* trailing 0x80 flush byte */<i_size; i_data++ ) |
752 | 23.5M | { |
753 | 23.5M | p_data[i_data] = bs_read( &s, 8 ); |
754 | 23.5M | if( bs_error(&s) ) |
755 | 632 | break; |
756 | 23.5M | } |
757 | | |
758 | | /* TS 101 154 Auxiliary Data and VC-1 video */ |
759 | 58.4k | static const uint8_t p_DVB1_user_identifier[] = { |
760 | 58.4k | 0x47, 0x41, 0x39, 0x34 /* user identifier */ |
761 | 58.4k | }; |
762 | | |
763 | | /* Check if we have DVB1_data() */ |
764 | 58.4k | if( i_data >= sizeof(p_DVB1_user_identifier) && |
765 | 55.5k | !memcmp( p_data, p_DVB1_user_identifier, sizeof(p_DVB1_user_identifier) ) ) |
766 | 29.4k | { |
767 | 29.4k | cc_ProbeAndExtract( &p_sys->cc_next, true, p_data, i_data ); |
768 | 29.4k | } |
769 | | |
770 | 58.4k | free( p_data ); |
771 | 58.4k | } |
772 | 58.4k | } |
773 | | |
774 | 1.81M | if( p_release ) |
775 | 398k | block_Release( p_release ); |
776 | 1.81M | return p_pic; |
777 | 1.81M | } |
778 | | |
779 | | /***************************************************************************** |
780 | | * GetCc: |
781 | | *****************************************************************************/ |
782 | | static block_t *GetCc( decoder_t *p_dec, decoder_cc_desc_t *p_desc ) |
783 | 197k | { |
784 | 197k | decoder_sys_t *p_sys = p_dec->p_sys; |
785 | 197k | block_t *p_cc; |
786 | | |
787 | 197k | p_cc = block_Alloc( p_sys->cc.i_data); |
788 | 197k | if( p_cc ) |
789 | 197k | { |
790 | 197k | memcpy( p_cc->p_buffer, p_sys->cc.p_data, p_sys->cc.i_data ); |
791 | 197k | p_cc->i_dts = |
792 | 197k | p_cc->i_pts = p_sys->cc.b_reorder ? p_sys->i_cc_pts : p_sys->i_cc_dts; |
793 | 197k | p_cc->i_flags = p_sys->i_cc_flags & BLOCK_FLAG_TYPE_MASK; |
794 | | |
795 | 197k | p_desc->i_608_channels = p_sys->cc.i_608channels; |
796 | 197k | p_desc->i_708_channels = p_sys->cc.i_708channels; |
797 | 197k | p_desc->i_reorder_depth = p_sys->cc.b_reorder ? 4 : -1; |
798 | 197k | } |
799 | 197k | cc_Flush( &p_sys->cc ); |
800 | 197k | return p_cc; |
801 | 197k | } |