00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #include <stdlib.h>
00045
00046 #include <vlc/vlc.h>
00047 #include <vlc/decoder.h>
00048 #include <vlc/input.h>
00049
00050 #include "vlc_block_helper.h"
00051
00052 #define SYNC_INTRAFRAME_TEXT N_("Sync on intraframe")
00053 #define SYNC_INTRAFRAME_LONGTEXT N_("Normally the packetizer would " \
00054 "sync on the next full frame. This flags instructs the packetizer " \
00055 "to sync on the first intraframe found.")
00056
00057
00058
00059
00060 static int Open ( vlc_object_t * );
00061 static void Close( vlc_object_t * );
00062
00063 vlc_module_begin();
00064 set_category( CAT_SOUT );
00065 set_subcategory( SUBCAT_SOUT_PACKETIZER );
00066 set_description( _("MPEG-I/II video packetizer") );
00067 set_capability( "packetizer", 50 );
00068 set_callbacks( Open, Close );
00069
00070 add_bool( "packetizer-mpegvideo-sync-iframe", 0, NULL, SYNC_INTRAFRAME_TEXT,
00071 SYNC_INTRAFRAME_LONGTEXT, VLC_TRUE );
00072 vlc_module_end();
00073
00074
00075
00076
00077 static block_t *Packetize( decoder_t *, block_t ** );
00078 static block_t *ParseMPEGBlock( decoder_t *, block_t * );
00079
00080 struct decoder_sys_t
00081 {
00082
00083
00084
00085 block_bytestream_t bytestream;
00086 int i_state;
00087 int i_offset;
00088 uint8_t p_startcode[3];
00089
00090
00091 block_t *p_seq;
00092 block_t *p_ext;
00093
00094
00095 block_t *p_frame;
00096 block_t **pp_last;
00097
00098 vlc_bool_t b_frame_slice;
00099 mtime_t i_pts;
00100 mtime_t i_dts;
00101
00102
00103 int i_frame_rate;
00104 int i_frame_rate_base;
00105 vlc_bool_t b_seq_progressive;
00106 vlc_bool_t b_low_delay;
00107 int i_aspect_ratio_info;
00108 vlc_bool_t b_inited;
00109
00110
00111 int i_temporal_ref;
00112 int i_picture_type;
00113 int i_picture_structure;
00114 int i_top_field_first;
00115 int i_repeat_first_field;
00116 int i_progressive_frame;
00117
00118 mtime_t i_interpolated_dts;
00119 mtime_t i_old_duration;
00120 mtime_t i_last_ref_pts;
00121
00122
00123 int i_seq_old;
00124
00125
00126 vlc_bool_t b_sync_on_intra_frame;
00127 vlc_bool_t b_discontinuity;
00128 };
00129
00130 enum {
00131 STATE_NOSYNC,
00132 STATE_NEXT_SYNC
00133 };
00134
00135
00136
00137
00138 static int Open( vlc_object_t *p_this )
00139 {
00140 decoder_t *p_dec = (decoder_t*)p_this;
00141 decoder_sys_t *p_sys;
00142
00143 if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'm', 'p', 'g', '1' ) &&
00144 p_dec->fmt_in.i_codec != VLC_FOURCC( 'm', 'p', 'g', '2' ) &&
00145 p_dec->fmt_in.i_codec != VLC_FOURCC( 'm', 'p', 'g', 'v' ) )
00146 {
00147 return VLC_EGENERIC;
00148 }
00149
00150 es_format_Init( &p_dec->fmt_out, VIDEO_ES, VLC_FOURCC('m','p','g','v') );
00151 p_dec->pf_packetize = Packetize;
00152
00153 p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
00154
00155
00156 p_sys->i_state = STATE_NOSYNC;
00157 p_sys->bytestream = block_BytestreamInit( p_dec );
00158 p_sys->p_startcode[0] = 0;
00159 p_sys->p_startcode[1] = 0;
00160 p_sys->p_startcode[2] = 1;
00161 p_sys->i_offset = 0;
00162
00163 p_sys->p_seq = NULL;
00164 p_sys->p_ext = NULL;
00165 p_sys->p_frame = NULL;
00166 p_sys->pp_last = &p_sys->p_frame;
00167 p_sys->b_frame_slice = VLC_FALSE;
00168
00169 p_sys->i_dts = p_sys->i_pts = 0;
00170
00171 p_sys->i_frame_rate = 1;
00172 p_sys->i_frame_rate_base = 1;
00173 p_sys->b_seq_progressive = VLC_TRUE;
00174 p_sys->b_low_delay = VLC_TRUE;
00175 p_sys->i_seq_old = 0;
00176
00177 p_sys->i_temporal_ref = 0;
00178 p_sys->i_picture_type = 0;
00179 p_sys->i_picture_structure = 0x03;
00180 p_sys->i_top_field_first = 0;
00181 p_sys->i_repeat_first_field = 0;
00182 p_sys->i_progressive_frame = 0;
00183 p_sys->b_inited = 0;
00184
00185 p_sys->i_interpolated_dts = 0;
00186 p_sys->i_old_duration = 0;
00187 p_sys->i_last_ref_pts = 0;
00188
00189 p_sys->b_discontinuity = VLC_FALSE;
00190 p_sys->b_sync_on_intra_frame = var_CreateGetBool( p_dec, "packetizer-mpegvideo-sync-iframe" );
00191 if( p_sys->b_sync_on_intra_frame )
00192 msg_Dbg( p_dec, "syncing happens on intraframe now." );
00193
00194 return VLC_SUCCESS;
00195 }
00196
00197
00198
00199
00200 static void Close( vlc_object_t *p_this )
00201 {
00202 decoder_t *p_dec = (decoder_t*)p_this;
00203 decoder_sys_t *p_sys = p_dec->p_sys;
00204
00205 block_BytestreamRelease( &p_sys->bytestream );
00206
00207 if( p_sys->p_seq )
00208 {
00209 block_Release( p_sys->p_seq );
00210 }
00211 if( p_sys->p_ext )
00212 {
00213 block_Release( p_sys->p_ext );
00214 }
00215 if( p_sys->p_frame )
00216 {
00217 block_ChainRelease( p_sys->p_frame );
00218 }
00219
00220 var_Destroy( p_dec, "packetizer-mpegvideo-sync-iframe" );
00221
00222 free( p_sys );
00223 }
00224
00225
00226
00227
00228 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
00229 {
00230 decoder_sys_t *p_sys = p_dec->p_sys;
00231 block_t *p_pic;
00232
00233 if( pp_block == NULL || *pp_block == NULL )
00234 {
00235 return NULL;
00236 }
00237
00238 if( (*pp_block)->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
00239 {
00240 p_sys->i_state = STATE_NOSYNC;
00241 p_sys->b_discontinuity = VLC_TRUE;
00242 if( p_sys->p_frame )
00243 block_ChainRelease( p_sys->p_frame );
00244 p_sys->p_frame = NULL;
00245 p_sys->pp_last = &p_sys->p_frame;
00246 p_sys->b_frame_slice = VLC_FALSE;
00247 block_Release( *pp_block );
00248 return NULL;
00249 }
00250
00251 block_BytestreamPush( &p_sys->bytestream, *pp_block );
00252
00253 while( 1 )
00254 {
00255 switch( p_sys->i_state )
00256 {
00257
00258 case STATE_NOSYNC:
00259 if( block_FindStartcodeFromOffset( &p_sys->bytestream,
00260 &p_sys->i_offset, p_sys->p_startcode, 3 ) == VLC_SUCCESS )
00261 {
00262 p_sys->i_state = STATE_NEXT_SYNC;
00263 }
00264
00265 if( p_sys->i_offset )
00266 {
00267 block_SkipBytes( &p_sys->bytestream, p_sys->i_offset );
00268 p_sys->i_offset = 0;
00269 block_BytestreamFlush( &p_sys->bytestream );
00270 }
00271
00272 if( p_sys->i_state != STATE_NEXT_SYNC )
00273 {
00274
00275 return NULL;
00276 }
00277
00278 p_sys->i_offset = 1;
00279
00280 case STATE_NEXT_SYNC:
00281
00282
00283
00284
00285 if( block_FindStartcodeFromOffset( &p_sys->bytestream,
00286 &p_sys->i_offset, p_sys->p_startcode, 3 ) != VLC_SUCCESS )
00287 {
00288
00289 return NULL;
00290 }
00291
00292
00293 p_pic = block_New( p_dec, p_sys->i_offset );
00294 block_BytestreamFlush( &p_sys->bytestream );
00295 p_pic->i_pts = p_sys->bytestream.p_block->i_pts;
00296 p_pic->i_dts = p_sys->bytestream.p_block->i_dts;
00297
00298 block_GetBytes( &p_sys->bytestream, p_pic->p_buffer,
00299 p_pic->i_buffer );
00300
00301
00302 if( p_pic->i_buffer >= 4 && p_pic->p_buffer[3] == 0x00 )
00303 {
00304
00305 p_sys->bytestream.p_block->i_pts = 0;
00306 p_sys->bytestream.p_block->i_dts = 0;
00307 }
00308
00309 p_sys->i_offset = 0;
00310
00311
00312 if( !( p_pic = ParseMPEGBlock( p_dec, p_pic ) ) )
00313 {
00314 p_sys->i_state = STATE_NOSYNC;
00315 break;
00316 }
00317
00318
00319
00320 if( p_sys->b_discontinuity &&
00321 p_sys->b_sync_on_intra_frame )
00322 {
00323 if( p_pic->i_flags & BLOCK_FLAG_TYPE_I )
00324 {
00325 msg_Dbg( p_dec, "synced on Intra frame" );
00326 p_sys->b_discontinuity = VLC_FALSE;
00327 p_pic->i_flags |= BLOCK_FLAG_DISCONTINUITY;
00328 }
00329 else
00330 {
00331 p_sys->i_state = STATE_NOSYNC;
00332 break;
00333 }
00334 }
00335
00336
00337
00338 if( p_sys->i_dts <= 0 && p_sys->i_pts <= 0 &&
00339 p_sys->i_interpolated_dts <= 0 )
00340 {
00341 msg_Dbg( p_dec, "need a starting pts/dts" );
00342 p_sys->i_state = STATE_NOSYNC;
00343 block_Release( p_pic );
00344 break;
00345 }
00346
00347
00348
00349 if( !p_pic->i_dts ) p_pic->i_dts = p_pic->i_pts;
00350
00351
00352 *pp_block = block_BytestreamPop( &p_sys->bytestream );
00353
00354 p_sys->i_state = STATE_NOSYNC;
00355
00356 return p_pic;
00357 }
00358 }
00359 }
00360
00361
00362
00363
00364 static block_t *ParseMPEGBlock( decoder_t *p_dec, block_t *p_frag )
00365 {
00366 decoder_sys_t *p_sys = p_dec->p_sys;
00367 block_t *p_pic = NULL;
00368
00369
00370
00371
00372 if( ( p_sys->b_frame_slice &&
00373 (p_frag->p_buffer[3] == 0x00 || p_frag->p_buffer[3] > 0xaf) ) &&
00374 p_sys->p_seq == NULL )
00375 {
00376
00377
00378 msg_Dbg( p_dec, "waiting for sequence start" );
00379 if( p_sys->p_frame ) block_ChainRelease( p_sys->p_frame );
00380 p_sys->p_frame = NULL;
00381 p_sys->pp_last = &p_sys->p_frame;
00382 p_sys->b_frame_slice = VLC_FALSE;
00383
00384 }
00385 else if( p_sys->b_frame_slice &&
00386 (p_frag->p_buffer[3] == 0x00 || p_frag->p_buffer[3] > 0xaf) )
00387 {
00388 mtime_t i_duration;
00389
00390 p_pic = block_ChainGather( p_sys->p_frame );
00391
00392 i_duration = (mtime_t)( 1000000 * p_sys->i_frame_rate_base /
00393 p_sys->i_frame_rate );
00394
00395 if( !p_sys->b_seq_progressive && p_sys->i_picture_structure != 0x03 )
00396 {
00397 i_duration /= 2;
00398 }
00399
00400 if( p_sys->b_seq_progressive )
00401 {
00402 if( p_sys->i_top_field_first == 0 &&
00403 p_sys->i_repeat_first_field == 1 )
00404 {
00405 i_duration *= 2;
00406 }
00407 else if( p_sys->i_top_field_first == 1 &&
00408 p_sys->i_repeat_first_field == 1 )
00409 {
00410 i_duration *= 3;
00411 }
00412 }
00413 else
00414 {
00415 if( p_sys->i_picture_structure == 0x03 )
00416 {
00417 if( p_sys->i_progressive_frame && p_sys->i_repeat_first_field )
00418 {
00419 i_duration += i_duration / 2;
00420 }
00421 }
00422 }
00423
00424 if( p_sys->b_low_delay || p_sys->i_picture_type == 0x03 )
00425 {
00426
00427
00428 if( p_sys->i_pts > 0 ) p_sys->i_interpolated_dts = p_sys->i_pts;
00429 if( p_sys->i_dts > 0 ) p_sys->i_interpolated_dts = p_sys->i_dts;
00430 }
00431 else
00432 {
00433
00434 if( p_sys->i_last_ref_pts > 0 )
00435 p_sys->i_interpolated_dts = p_sys->i_last_ref_pts;
00436 if( p_sys->i_dts > 0 ) p_sys->i_interpolated_dts = p_sys->i_dts;
00437
00438 p_sys->i_last_ref_pts = p_sys->i_pts;
00439 }
00440
00441 p_pic->i_dts = p_sys->i_interpolated_dts;
00442
00443
00444 if( p_sys->i_pts > 0 )
00445 {
00446 p_pic->i_pts = p_sys->i_pts;
00447 }
00448 else if( p_sys->i_picture_type == 0x03 )
00449 {
00450 p_pic->i_pts = p_pic->i_dts;
00451 }
00452 else
00453 {
00454 p_pic->i_pts = 0;
00455 }
00456
00457 if( p_sys->b_low_delay || p_sys->i_picture_type == 0x03 )
00458 {
00459
00460 p_sys->i_interpolated_dts += i_duration;
00461 }
00462 else
00463 {
00464 p_sys->i_interpolated_dts += p_sys->i_old_duration;
00465 p_sys->i_old_duration = i_duration;
00466 }
00467
00468 switch ( p_sys->i_picture_type )
00469 {
00470 case 0x01:
00471 p_pic->i_flags |= BLOCK_FLAG_TYPE_I;
00472 break;
00473 case 0x02:
00474 p_pic->i_flags |= BLOCK_FLAG_TYPE_P;
00475 break;
00476 case 0x03:
00477 p_pic->i_flags |= BLOCK_FLAG_TYPE_B;
00478 break;
00479 }
00480
00481 p_pic->i_length = p_sys->i_interpolated_dts - p_pic->i_dts;
00482
00483 #if 0
00484 msg_Dbg( p_dec, "pic: type=%d dts="I64Fd" pts-dts="I64Fd,
00485 p_sys->i_picture_type, p_pic->i_dts, p_pic->i_pts - p_pic->i_dts);
00486 #endif
00487
00488
00489 p_sys->p_frame = NULL;
00490 p_sys->pp_last = &p_sys->p_frame;
00491 p_sys->b_frame_slice = VLC_FALSE;
00492 }
00493
00494
00495
00496
00497 if( p_frag->p_buffer[3] == 0xb8 )
00498 {
00499
00500 if( p_sys->p_seq &&
00501 p_sys->i_seq_old > p_sys->i_frame_rate/p_sys->i_frame_rate_base )
00502 {
00503
00504 block_ChainLastAppend( &p_sys->pp_last, block_Duplicate( p_sys->p_seq ) );
00505 if( p_sys->p_ext )
00506 {
00507 block_ChainLastAppend( &p_sys->pp_last, block_Duplicate( p_sys->p_ext ) );
00508 }
00509
00510 p_sys->i_seq_old = 0;
00511 }
00512 }
00513 else if( p_frag->p_buffer[3] == 0xb3 && p_frag->i_buffer >= 8 )
00514 {
00515
00516 static const int code_to_frame_rate[16][2] =
00517 {
00518 { 1, 1 },
00519 { 24000, 1001 }, { 24, 1 }, { 25, 1 }, { 30000, 1001 },
00520 { 30, 1 }, { 50, 1 }, { 60000, 1001 }, { 60, 1 },
00521
00522 { 15, 1001 },
00523
00524 { 5, 1001 }, { 10, 1001 }, { 12, 1001 }, { 15, 1001 },
00525 { 1, 1 }, { 1, 1 }
00526 };
00527
00528 if( p_sys->p_seq ) block_Release( p_sys->p_seq );
00529 if( p_sys->p_ext ) block_Release( p_sys->p_ext );
00530
00531 p_sys->p_seq = block_Duplicate( p_frag );
00532 p_sys->i_seq_old = 0;
00533 p_sys->p_ext = NULL;
00534
00535 p_dec->fmt_out.video.i_width =
00536 ( p_frag->p_buffer[4] << 4)|(p_frag->p_buffer[5] >> 4 );
00537 p_dec->fmt_out.video.i_height =
00538 ( (p_frag->p_buffer[5]&0x0f) << 8 )|p_frag->p_buffer[6];
00539 p_sys->i_aspect_ratio_info = p_frag->p_buffer[7] >> 4;
00540
00541
00542
00543 p_sys->i_frame_rate = code_to_frame_rate[p_frag->p_buffer[7]&0x0f][0];
00544 p_sys->i_frame_rate_base =
00545 code_to_frame_rate[p_frag->p_buffer[7]&0x0f][1];
00546
00547 p_dec->fmt_out.video.i_frame_rate = p_sys->i_frame_rate;
00548 p_dec->fmt_out.video.i_frame_rate_base = p_sys->i_frame_rate_base;
00549
00550 p_sys->b_seq_progressive = VLC_TRUE;
00551 p_sys->b_low_delay = VLC_TRUE;
00552
00553 if ( !p_sys->b_inited )
00554 {
00555 msg_Dbg( p_dec, "Size %dx%d fps=%.3f",
00556 p_dec->fmt_out.video.i_width, p_dec->fmt_out.video.i_height,
00557 p_sys->i_frame_rate / (float)p_sys->i_frame_rate_base );
00558 p_sys->b_inited = 1;
00559 }
00560 }
00561 else if( p_frag->p_buffer[3] == 0xb5 )
00562 {
00563 int i_type = p_frag->p_buffer[4] >> 4;
00564
00565
00566 if( i_type == 0x01 )
00567 {
00568 #if 0
00569 static const int mpeg2_aspect[16][2] =
00570 {
00571 {0,1}, {1,1}, {4,3}, {16,9}, {221,100},
00572 {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1},
00573 {0,1}, {0,1}
00574 };
00575 #endif
00576
00577
00578 if( p_sys->p_ext) block_Release( p_sys->p_ext );
00579 p_sys->p_ext = block_Duplicate( p_frag );
00580
00581 if( p_frag->i_buffer >= 10 )
00582 {
00583 p_sys->b_seq_progressive =
00584 p_frag->p_buffer[5]&0x08 ? VLC_TRUE : VLC_FALSE;
00585 p_sys->b_low_delay =
00586 p_frag->p_buffer[9]&0x80 ? VLC_TRUE : VLC_FALSE;
00587 }
00588
00589
00590
00591
00592
00593
00594
00595 #if 0
00596 p_dec->fmt_out.video.i_aspect =
00597 mpeg2_aspect[p_sys->i_aspect_ratio_info][0] *
00598 VOUT_ASPECT_FACTOR /
00599 mpeg2_aspect[p_sys->i_aspect_ratio_info][1];
00600 #endif
00601
00602 }
00603 else if( i_type == 0x08 )
00604 {
00605
00606 p_sys->i_picture_structure = p_frag->p_buffer[6]&0x03;
00607 p_sys->i_top_field_first = p_frag->p_buffer[7] >> 7;
00608 p_sys->i_repeat_first_field= (p_frag->p_buffer[7]>>1)&0x01;
00609 p_sys->i_progressive_frame = p_frag->p_buffer[8] >> 7;
00610 }
00611 }
00612 else if( p_frag->p_buffer[3] == 0x00 )
00613 {
00614
00615 p_sys->i_seq_old++;
00616
00617 if( p_frag->i_buffer >= 6 )
00618 {
00619 p_sys->i_temporal_ref =
00620 ( p_frag->p_buffer[4] << 2 )|(p_frag->p_buffer[5] >> 6);
00621 p_sys->i_picture_type = ( p_frag->p_buffer[5] >> 3 ) & 0x03;
00622 }
00623
00624 p_sys->i_dts = p_frag->i_dts;
00625 p_sys->i_pts = p_frag->i_pts;
00626 }
00627 else if( p_frag->p_buffer[3] >= 0x01 && p_frag->p_buffer[3] <= 0xaf )
00628 {
00629
00630 p_sys->b_frame_slice = VLC_TRUE;
00631 }
00632
00633
00634 block_ChainLastAppend( &p_sys->pp_last, p_frag );
00635
00636 return p_pic;
00637 }