1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001, 2002, 2006 the VideoLAN team
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Gildas Bazin <gbazin@videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
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 General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_codec.h>
36 #include <vlc_block.h>
39 #include "vlc_block_helper.h"
41 /*****************************************************************************
43 *****************************************************************************/
44 static int Open ( vlc_object_t * );
45 static void Close( vlc_object_t * );
48 set_category( CAT_SOUT )
49 set_subcategory( SUBCAT_SOUT_PACKETIZER )
50 set_description( N_("VC-1 packetizer") )
51 set_capability( "packetizer", 50 )
52 set_callbacks( Open, Close )
55 /*****************************************************************************
57 *****************************************************************************/
63 block_bytestream_t bytestream;
66 uint8_t p_startcode[3];
68 /* Current sequence header */
69 bool b_sequence_header;
73 bool b_advanced_profile;
75 bool b_frame_interpolation;
76 bool b_range_reduction;
88 /* Current frame being built */
93 mtime_t i_interpolated_dts;
104 IDU_TYPE_SEQUENCE_HEADER = 0x0f,
105 IDU_TYPE_ENTRY_POINT = 0x0e,
106 IDU_TYPE_FRAME = 0x0D,
107 IDU_TYPE_FIELD = 0x0C,
108 IDU_TYPE_SLICE = 0x0B,
109 IDU_TYPE_END_OF_SEQUENCE = 0x0A,
111 IDU_TYPE_SEQUENCE_LEVEL_USER_DATA = 0x1F,
112 IDU_TYPE_ENTRY_POINT_USER_DATA = 0x1E,
113 IDU_TYPE_FRAME_USER_DATA = 0x1D,
114 IDU_TYPE_FIELD_USER_DATA = 0x1C,
115 IDU_TYPE_SLICE_USER_DATA = 0x1B,
118 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block );
120 /*****************************************************************************
121 * Open: probe the packetizer and return score
122 *****************************************************************************
123 * Tries to launch a decoder and return score so that the interface is able
125 *****************************************************************************/
126 static int Open( vlc_object_t *p_this )
128 decoder_t *p_dec = (decoder_t*)p_this;
129 decoder_sys_t *p_sys;
131 if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'W', 'V', 'C', '1' ) )
134 p_dec->pf_packetize = Packetize;
136 /* Create the output format */
137 es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
138 p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
140 p_sys->i_state = STATE_NOSYNC;
141 p_sys->bytestream = block_BytestreamInit();
142 p_sys->p_startcode[0] = 0x00;
143 p_sys->p_startcode[1] = 0x00;
144 p_sys->p_startcode[2] = 0x01;
147 p_sys->b_sequence_header = false;
148 p_sys->sh.p_sh = NULL;
149 p_sys->b_entry_point = false;
150 p_sys->ep.p_ep = NULL;
152 p_sys->b_frame = false;
153 p_sys->p_frame = NULL;
154 p_sys->pp_last = &p_sys->p_frame;
156 p_sys->i_interpolated_dts = -1;
159 if( p_dec->fmt_out.i_extra > 0 )
161 uint8_t *p_extra = p_dec->fmt_out.p_extra;
163 /* With (some) ASF the first byte has to be stripped */
164 if( p_extra[0] != 0x00 )
166 memcpy( &p_extra[0], &p_extra[1], p_dec->fmt_out.i_extra - 1 );
167 p_dec->fmt_out.i_extra--;
171 if( p_dec->fmt_out.i_extra > 0 )
173 block_t *p_init = block_New( p_dec, p_dec->fmt_out.i_extra );
175 memcpy( p_init->p_buffer, p_dec->fmt_out.p_extra,
176 p_dec->fmt_out.i_extra );
179 while( ( p_pic = Packetize( p_dec, &p_init ) ) )
180 block_Release( p_pic ); /* Should not happen (only sequence header) */
187 /*****************************************************************************
189 *****************************************************************************/
190 static void Close( vlc_object_t *p_this )
192 decoder_t *p_dec = (decoder_t*)p_this;
193 decoder_sys_t *p_sys = p_dec->p_sys;
195 block_BytestreamRelease( &p_sys->bytestream );
197 block_Release( p_sys->p_frame );
201 /*****************************************************************************
202 * Packetize: packetize an access unit
203 *****************************************************************************/
204 static block_t *ParseIDU( decoder_t *p_dec, bool *pb_used_ts, block_t *p_frag );
206 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
208 decoder_sys_t *p_sys = p_dec->p_sys;
211 if( pp_block == NULL || *pp_block == NULL )
214 if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
216 if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )
218 p_sys->i_state = STATE_NOSYNC;
219 block_BytestreamEmpty( &p_sys->bytestream );
222 block_ChainRelease( p_sys->p_frame );
223 p_sys->p_frame = NULL;
224 p_sys->pp_last = &p_sys->p_frame;
225 p_sys->b_frame = false;
227 p_sys->i_interpolated_dts = 0;
228 block_Release( *pp_block );
232 block_BytestreamPush( &p_sys->bytestream, *pp_block );
238 switch( p_sys->i_state )
242 if( block_FindStartcodeFromOffset( &p_sys->bytestream, &p_sys->i_offset, p_sys->p_startcode, 3 ) == VLC_SUCCESS )
243 p_sys->i_state = STATE_NEXT_SYNC;
245 if( p_sys->i_offset )
247 block_SkipBytes( &p_sys->bytestream, p_sys->i_offset );
249 block_BytestreamFlush( &p_sys->bytestream );
252 if( p_sys->i_state != STATE_NEXT_SYNC )
253 return NULL; /* Need more data */
255 p_sys->i_offset = 4; /* To find next startcode */
257 case STATE_NEXT_SYNC:
258 /* TODO: If p_block == NULL, flush the buffer without checking the
261 /* Find the next startcode */
262 if( block_FindStartcodeFromOffset( &p_sys->bytestream, &p_sys->i_offset, p_sys->p_startcode, 3 ) != VLC_SUCCESS )
263 return NULL; /* Need more data */
265 /* Get the new fragment and set the pts/dts */
266 p_pic = block_New( p_dec, p_sys->i_offset );
267 block_BytestreamFlush( &p_sys->bytestream );
268 p_pic->i_pts = p_sys->bytestream.p_block->i_pts;
269 p_pic->i_dts = p_sys->bytestream.p_block->i_dts;
271 block_GetBytes( &p_sys->bytestream, p_pic->p_buffer, p_pic->i_buffer );
275 /* Parse and return complete frame */
276 p_pic = ParseIDU( p_dec, &b_used_ts, p_pic );
278 /* Don't reuse the same timestamps several times */
281 p_sys->bytestream.p_block->i_pts = -1;
282 p_sys->bytestream.p_block->i_dts = -1;
288 p_sys->i_state = STATE_NOSYNC;
292 if( p_sys->i_interpolated_dts < 0 )
294 msg_Dbg( p_dec, "need a starting pts/dts" );
295 p_sys->i_state = STATE_NOSYNC;
296 block_Release( p_pic );
300 /* So p_block doesn't get re-added several times */
301 *pp_block = block_BytestreamPop( &p_sys->bytestream );
303 p_sys->i_state = STATE_NOSYNC;
310 /* DecodeRIDU: decode the startcode emulation prevention (same than h264) */
311 static void DecodeRIDU( uint8_t *p_ret, int *pi_ret, uint8_t *src, int i_src )
313 uint8_t *end = &src[i_src];
314 uint8_t *dst_end = &p_ret[*pi_ret];
315 uint8_t *dst = p_ret;
317 while( src < end && dst < dst_end )
319 if( src < end - 3 && src[0] == 0x00 && src[1] == 0x00 &&
331 *pi_ret = dst - p_ret;
333 /* BuildExtraData: gather sequence header and entry point */
334 static void BuildExtraData( decoder_t *p_dec )
336 decoder_sys_t *p_sys = p_dec->p_sys;
337 es_format_t *p_es = &p_dec->fmt_out;
339 if( !p_sys->b_sequence_header || !p_sys->b_entry_point )
342 i_extra = p_sys->sh.p_sh->i_buffer + p_sys->ep.p_ep->i_buffer;
343 if( p_es->i_extra != i_extra )
345 p_es->i_extra = i_extra;
346 p_es->p_extra = realloc( p_dec->fmt_out.p_extra, p_es->i_extra );
348 memcpy( p_es->p_extra,
349 p_sys->sh.p_sh->p_buffer, p_sys->sh.p_sh->i_buffer );
350 memcpy( (uint8_t*)p_es->p_extra + p_sys->sh.p_sh->i_buffer,
351 p_sys->ep.p_ep->p_buffer, p_sys->ep.p_ep->i_buffer );
353 /* ParseIDU: parse an Independent Decoding Unit */
354 static block_t *ParseIDU( decoder_t *p_dec, bool *pb_used_ts, block_t *p_frag )
356 decoder_sys_t *p_sys = p_dec->p_sys;
358 const idu_type_t idu = p_frag->p_buffer[3];
361 if( !p_sys->b_sequence_header && idu != IDU_TYPE_SEQUENCE_HEADER )
363 msg_Warn( p_dec, "waiting for sequence header" );
364 block_Release( p_frag );
367 if( p_sys->b_sequence_header && !p_sys->b_entry_point && idu != IDU_TYPE_ENTRY_POINT )
369 msg_Warn( p_dec, "waiting for entry point" );
370 block_Release( p_frag );
373 /* TODO we do not gather ENTRY_POINT and SEQUENCE_DATA user data
374 * But It should not be a problem for decoder */
376 /* Do we have completed a frame */
378 if( p_sys->b_frame &&
379 idu != IDU_TYPE_FRAME_USER_DATA &&
380 idu != IDU_TYPE_FIELD && idu != IDU_TYPE_FIELD_USER_DATA &&
381 idu != IDU_TYPE_SLICE && idu != IDU_TYPE_SLICE_USER_DATA &&
382 idu != IDU_TYPE_END_OF_SEQUENCE )
385 p_pic = block_ChainGather( p_sys->p_frame );
388 if( p_pic->i_dts > 0 )
389 p_sys->i_interpolated_dts = p_pic->i_dts;
391 /* We can interpolate dts/pts only if we have a frame rate */
392 if( p_dec->fmt_out.video.i_frame_rate != 0 && p_dec->fmt_out.video.i_frame_rate_base != 0 )
394 if( p_sys->i_interpolated_dts > 0 )
395 p_sys->i_interpolated_dts += INT64_C(1000000) *
396 p_dec->fmt_out.video.i_frame_rate_base /
397 p_dec->fmt_out.video.i_frame_rate;
399 //msg_Dbg( p_dec, "-------------- XXX0 dts=%"PRId64" pts=%"PRId64" interpolated=%"PRId64,
400 // p_pic->i_dts, p_pic->i_pts, p_sys->i_interpolated_dts );
401 if( p_pic->i_dts <= 0 )
402 p_pic->i_dts = p_sys->i_interpolated_dts;
404 if( p_pic->i_pts <= 0 )
406 if( !p_sys->sh.b_has_bframe || (p_pic->i_flags & BLOCK_FLAG_TYPE_B ) )
407 p_pic->i_pts = p_pic->i_dts;
408 /* TODO compute pts for other case */
412 //msg_Dbg( p_dec, "-------------- dts=%"PRId64" pts=%"PRId64, p_pic->i_dts, p_pic->i_pts );
415 p_sys->b_frame = false;
416 p_sys->p_frame = NULL;
417 p_sys->pp_last = &p_sys->p_frame;
423 block_t *p_frame = p_sys->p_frame;
424 if( p_frame->i_dts <= 0 && p_frame->i_pts <= 0 )
426 p_frame->i_dts = p_frag->i_dts;
427 p_frame->i_pts = p_frag->i_pts;
431 block_ChainLastAppend( &p_sys->pp_last, p_frag );
434 if( idu == IDU_TYPE_SEQUENCE_HEADER )
436 es_format_t *p_es = &p_dec->fmt_out;
440 int i_ridu = sizeof(ridu);
444 block_Release( p_sys->sh.p_sh );
445 p_sys->sh.p_sh = block_Duplicate( p_frag );
447 /* Extract the raw IDU */
448 DecodeRIDU( ridu, &i_ridu, &p_frag->p_buffer[4], p_frag->i_buffer - 4 );
450 /* Auto detect VC-1_SPMP_PESpacket_PayloadFormatHeader (SMPTE RP 227) for simple/main profile
451 * TODO find a test case and valid it */
452 if( i_ridu > 4 && (ridu[0]&0x80) == 0 ) /* for advanced profile, the first bit is 1 */
454 video_format_t *p_v = &p_dec->fmt_in.video;
455 const size_t i_potential_width = GetWBE( &ridu[0] );
456 const size_t i_potential_height = GetWBE( &ridu[2] );
458 if( i_potential_width >= 2 && i_potential_width <= 8192 &&
459 i_potential_height >= 2 && i_potential_height <= 8192 )
461 if( ( p_v->i_width <= 0 && p_v->i_height <= 0 ) ||
462 ( p_v->i_width == i_potential_width && p_v->i_height == i_potential_height ) )
464 static const uint8_t startcode[4] = { 0x00, 0x00, 0x01, IDU_TYPE_SEQUENCE_HEADER };
465 p_es->video.i_width = i_potential_width;
466 p_es->video.i_height = i_potential_height;
469 p_frag->p_buffer += 4;
470 p_frag->i_buffer -= 4;
471 memcpy( p_frag->p_buffer, startcode, sizeof(startcode) );
477 bs_init( &s, ridu, i_ridu );
478 i_profile = bs_read( &s, 2 );
481 const int i_level = bs_read( &s, 3 );
483 /* Advanced profile */
484 p_sys->sh.b_advanced_profile = true;
485 p_sys->sh.b_range_reduction = false;
486 p_sys->sh.b_has_bframe = true;
488 bs_skip( &s, 2+3+5+1 ); // chroma format + frame rate Q + bit rate Q + postprocflag
490 p_es->video.i_width = 2*bs_read( &s, 12 )+2;
491 p_es->video.i_height = 2*bs_read( &s, 12 )+2;
493 if( !p_sys->b_sequence_header )
494 msg_Dbg( p_dec, "found sequence header for advanced profile level L%d resolution %dx%d",
495 i_level, p_es->video.i_width, p_es->video.i_height);
497 bs_skip( &s, 1 );// pulldown
498 p_sys->sh.b_interlaced = bs_read( &s, 1 );
499 bs_skip( &s, 1 );// frame counter
500 p_sys->sh.b_frame_interpolation = bs_read( &s, 1 );
501 bs_skip( &s, 1 ); // Reserved
502 bs_skip( &s, 1 ); // Psf
504 if( bs_read( &s, 1 ) ) /* Display extension */
506 const int i_display_width = bs_read( &s, 14 )+1;
507 const int i_display_height = bs_read( &s, 14 )+1;
509 p_es->video.i_aspect = VOUT_ASPECT_FACTOR * i_display_width / i_display_height;
511 if( !p_sys->b_sequence_header )
512 msg_Dbg( p_dec, "display size %dx%d", i_display_width, i_display_height );
514 if( bs_read( &s, 1 ) ) /* Pixel aspect ratio (PAR/SAR) */
516 static const int p_ar[16][2] = {
517 { 0, 0}, { 1, 1}, {12,11}, {10,11}, {16,11}, {40,33},
518 {24,11}, {20,11}, {32,11}, {80,33}, {18,11}, {15,11},
519 {64,33}, {160,99},{ 0, 0}, { 0, 0}
521 int i_ar = bs_read( &s, 4 );
522 unsigned i_ar_w, i_ar_h;
526 i_ar_w = bs_read( &s, 8 );
527 i_ar_h = bs_read( &s, 8 );
531 i_ar_w = p_ar[i_ar][0];
532 i_ar_h = p_ar[i_ar][1];
534 vlc_ureduce( &i_ar_w, &i_ar_h, i_ar_w, i_ar_h, 0 );
535 if( !p_sys->b_sequence_header )
536 msg_Dbg( p_dec, "aspect ratio %d:%d", i_ar_w, i_ar_h );
539 if( bs_read( &s, 1 ) ) /* Frame rate */
543 if( bs_read( &s, 1 ) )
545 i_fps_num = bs_read( &s, 16 )+1;
550 const int i_nr = bs_read( &s, 8 );
551 const int i_dn = bs_read( &s, 4 );
555 case 1: i_fps_num = 24000; break;
556 case 2: i_fps_num = 25000; break;
557 case 3: i_fps_num = 30000; break;
558 case 4: i_fps_num = 50000; break;
559 case 5: i_fps_num = 60000; break;
560 case 6: i_fps_num = 48000; break;
561 case 7: i_fps_num = 72000; break;
565 case 1: i_fps_den = 1000; break;
566 case 2: i_fps_den = 1001; break;
569 if( i_fps_num != 0 && i_fps_den != 0 )
570 vlc_ureduce( &p_es->video.i_frame_rate, &p_es->video.i_frame_rate_base, i_fps_num, i_fps_den, 0 );
572 if( !p_sys->b_sequence_header )
573 msg_Dbg( p_dec, "frame rate %d/%d", p_es->video.i_frame_rate, p_es->video.i_frame_rate_base );
578 /* Simple and main profile */
579 p_sys->sh.b_advanced_profile = false;
580 p_sys->sh.b_interlaced = false;
582 if( !p_sys->b_sequence_header )
583 msg_Dbg( p_dec, "found sequence header for %s profile", i_profile == 0 ? "simple" : "main" );
585 bs_skip( &s, 2+3+5+1+1+ // reserved + frame rate Q + bit rate Q + loop filter + reserved
586 1+1+1+1+2+ // multiresolution + reserved + fast uv mc + extended mv + dquant
587 1+1+1+1 ); // variable size transform + reserved + overlap + sync marker
588 p_sys->sh.b_range_reduction = bs_read( &s, 1 );
589 if( bs_read( &s, 3 ) > 0 )
590 p_sys->sh.b_has_bframe = true;
592 p_sys->sh.b_has_bframe = false;
593 bs_skip( &s, 2 ); // quantizer
595 p_sys->sh.b_frame_interpolation = bs_read( &s, 1 );
597 p_sys->b_sequence_header = true;
598 BuildExtraData( p_dec );
600 else if( idu == IDU_TYPE_ENTRY_POINT )
603 block_Release( p_sys->ep.p_ep );
604 p_sys->ep.p_ep = block_Duplicate( p_frag );
606 p_sys->b_entry_point = true;
607 BuildExtraData( p_dec );
609 else if( idu == IDU_TYPE_FRAME )
613 int i_ridu = sizeof(ridu);
615 /* Extract the raw IDU */
616 DecodeRIDU( ridu, &i_ridu, &p_frag->p_buffer[4], p_frag->i_buffer - 4 );
618 /* Parse it + interpolate pts/dts if possible */
619 bs_init( &s, ridu, i_ridu );
621 if( p_sys->sh.b_advanced_profile )
625 if( p_sys->sh.b_interlaced )
627 if( bs_read( &s, 1 ) )
629 if( bs_read( &s, 1 ) )
630 i_fcm = 1; /* interlaced field */
632 i_fcm = 2; /* interlaced frame */
636 if( i_fcm == 1 ) /*interlaced field */
638 /* XXX for mixed I/P we should check reference usage before marking them I (too much work) */
639 switch( bs_read( &s, 3 ) )
644 p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I;
645 p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I;
646 p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I;
649 p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P;
655 p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B;
661 if( !bs_read( &s, 1 ) )
662 p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P;
663 else if( !bs_read( &s, 1 ) )
664 p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B;
665 else if( !bs_read( &s, 1 ) )
666 p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I;
667 else if( !bs_read( &s, 1 ) )
668 p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B; /* Bi */
670 p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P; /* P Skip */
675 if( p_sys->sh.b_frame_interpolation )
676 bs_skip( &s, 1 ); // interpolate
677 bs_skip( &s, 2 ); // frame count
678 if( p_sys->sh.b_range_reduction )
679 bs_skip( &s, 1 ); // range reduction
681 if( bs_read( &s, 1 ) )
682 p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P;
683 else if( !p_sys->sh.b_has_bframe || bs_read( &s, 1 ) )
684 p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I;
686 p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B;
688 p_sys->b_frame = true;