1 /*****************************************************************************
2 * mpegvideo.c: parse and packetize an MPEG1/2 video stream
3 *****************************************************************************
4 * Copyright (C) 2001-2006 VLC authors and VideoLAN
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Eric Petit <titer@videolan.org>
9 * Gildas Bazin <gbazin@videolan.org>
10 * Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU Lesser General Public License as published by
14 * the Free Software Foundation; either version 2.1 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public License
23 * along with this program; if not, write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
27 /*****************************************************************************
28 * Problem with this implementation:
30 * Although we should time-stamp each picture with a PTS, this isn't possible
31 * with the current implementation.
32 * The problem comes from the fact that for non-low-delay streams we can't
33 * calculate the PTS of pictures used as backward reference. Even the temporal
34 * reference number doesn't help here because all the pictures don't
35 * necessarily have the same duration (eg. 3:2 pulldown).
37 * However this doesn't really matter as far as the MPEG muxers are concerned
38 * because they allow having empty PTS fields. --gibalou
39 *****************************************************************************/
41 /*****************************************************************************
43 *****************************************************************************/
49 #include <vlc_common.h>
50 #include <vlc_plugin.h>
51 #include <vlc_block.h>
52 #include <vlc_codec.h>
53 #include <vlc_block_helper.h>
54 #include "../codec/cc.h"
55 #include "packetizer_helper.h"
57 #define SYNC_INTRAFRAME_TEXT N_("Sync on Intra Frame")
58 #define SYNC_INTRAFRAME_LONGTEXT N_("Normally the packetizer would " \
59 "sync on the next full frame. This flags instructs the packetizer " \
60 "to sync on the first Intra Frame found.")
62 /*****************************************************************************
64 *****************************************************************************/
65 static int Open ( vlc_object_t * );
66 static void Close( vlc_object_t * );
69 set_category( CAT_SOUT )
70 set_subcategory( SUBCAT_SOUT_PACKETIZER )
71 set_description( N_("MPEG-I/II video packetizer") )
72 set_shortname( N_("MPEG Video") )
73 set_capability( "packetizer", 50 )
74 set_callbacks( Open, Close )
76 add_bool( "packetizer-mpegvideo-sync-iframe", false, SYNC_INTRAFRAME_TEXT,
77 SYNC_INTRAFRAME_LONGTEXT, true )
80 /*****************************************************************************
82 *****************************************************************************/
88 packetizer_t packetizer;
90 /* Sequence header and extension */
94 /* Current frame being built */
102 /* Sequence properties */
104 int i_frame_rate_base;
105 bool b_seq_progressive;
107 int i_aspect_ratio_info;
110 /* Picture properties */
113 int i_picture_structure;
114 int i_top_field_first;
115 int i_repeat_first_field;
116 int i_progressive_frame;
118 mtime_t i_interpolated_dts;
119 mtime_t i_last_ref_pts;
122 /* Number of pictures since last sequence header */
126 bool b_sync_on_intra_frame;
127 bool b_discontinuity;
137 static block_t *Packetize( decoder_t *, block_t ** );
138 static block_t *GetCc( decoder_t *p_dec, bool pb_present[4] );
140 static void PacketizeReset( void *p_private, bool b_broken );
141 static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t * );
142 static int PacketizeValidate( void *p_private, block_t * );
144 static block_t *ParseMPEGBlock( decoder_t *, block_t * );
146 static const uint8_t p_mp2v_startcode[3] = { 0x00, 0x00, 0x01 };
148 /*****************************************************************************
150 *****************************************************************************/
151 static int Open( vlc_object_t *p_this )
153 decoder_t *p_dec = (decoder_t*)p_this;
154 decoder_sys_t *p_sys;
156 if( p_dec->fmt_in.i_codec != VLC_CODEC_MPGV )
159 es_format_Init( &p_dec->fmt_out, VIDEO_ES, VLC_CODEC_MPGV );
160 p_dec->fmt_out.i_original_fourcc = p_dec->fmt_in.i_original_fourcc;
163 p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
166 memset( p_dec->p_sys, 0, sizeof( decoder_sys_t ) );
169 packetizer_Init( &p_sys->packetizer,
170 p_mp2v_startcode, sizeof(p_mp2v_startcode),
172 PacketizeReset, PacketizeParse, PacketizeValidate, p_dec );
176 p_sys->p_frame = NULL;
177 p_sys->pp_last = &p_sys->p_frame;
178 p_sys->b_frame_slice = false;
180 p_sys->i_dts = p_sys->i_pts = VLC_TS_INVALID;
182 p_sys->i_frame_rate = 1;
183 p_sys->i_frame_rate_base = 1;
184 p_sys->b_seq_progressive = true;
185 p_sys->b_low_delay = true;
186 p_sys->i_seq_old = 0;
188 p_sys->i_temporal_ref = 0;
189 p_sys->i_picture_type = 0;
190 p_sys->i_picture_structure = 0x03; /* frame */
191 p_sys->i_top_field_first = 0;
192 p_sys->i_repeat_first_field = 0;
193 p_sys->i_progressive_frame = 0;
196 p_sys->i_interpolated_dts = VLC_TS_INVALID;
197 p_sys->i_last_ref_pts = VLC_TS_INVALID;
198 p_sys->b_second_field = 0;
200 p_sys->b_discontinuity = false;
201 p_sys->b_sync_on_intra_frame = var_CreateGetBool( p_dec, "packetizer-mpegvideo-sync-iframe" );
202 if( p_sys->b_sync_on_intra_frame )
203 msg_Dbg( p_dec, "syncing on intra frame now" );
205 p_sys->b_cc_reset = false;
208 p_sys->i_cc_flags = 0;
209 cc_Init( &p_sys->cc );
211 p_dec->pf_packetize = Packetize;
212 p_dec->pf_get_cc = GetCc;
217 /*****************************************************************************
219 *****************************************************************************/
220 static void Close( vlc_object_t *p_this )
222 decoder_t *p_dec = (decoder_t*)p_this;
223 decoder_sys_t *p_sys = p_dec->p_sys;
227 block_Release( p_sys->p_seq );
231 block_Release( p_sys->p_ext );
235 block_ChainRelease( p_sys->p_frame );
237 packetizer_Clean( &p_sys->packetizer );
239 var_Destroy( p_dec, "packetizer-mpegvideo-sync-iframe" );
244 /*****************************************************************************
246 *****************************************************************************/
247 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
249 decoder_sys_t *p_sys = p_dec->p_sys;
251 return packetizer_Packetize( &p_sys->packetizer, pp_block );
254 /*****************************************************************************
256 *****************************************************************************/
257 static block_t *GetCc( decoder_t *p_dec, bool pb_present[4] )
259 decoder_sys_t *p_sys = p_dec->p_sys;
263 for( i = 0; i < 4; i++ )
264 pb_present[i] = p_sys->cc.pb_present[i];
266 if( p_sys->cc.i_data <= 0 )
269 p_cc = block_Alloc( p_sys->cc.i_data );
272 memcpy( p_cc->p_buffer, p_sys->cc.p_data, p_sys->cc.i_data );
274 p_cc->i_pts = p_sys->cc.b_reorder ? p_sys->i_cc_pts : p_sys->i_cc_dts;
275 p_cc->i_flags = ( p_sys->cc.b_reorder ? p_sys->i_cc_flags : BLOCK_FLAG_TYPE_P ) & ( BLOCK_FLAG_TYPE_I|BLOCK_FLAG_TYPE_P|BLOCK_FLAG_TYPE_B);
277 cc_Flush( &p_sys->cc );
281 /*****************************************************************************
283 *****************************************************************************/
284 static void PacketizeReset( void *p_private, bool b_broken )
286 decoder_t *p_dec = p_private;
287 decoder_sys_t *p_sys = p_dec->p_sys;
291 p_sys->b_discontinuity = true;
293 block_ChainRelease( p_sys->p_frame );
294 p_sys->p_frame = NULL;
295 p_sys->pp_last = &p_sys->p_frame;
296 p_sys->b_frame_slice = false;
300 p_sys->i_interpolated_dts =
301 p_sys->i_last_ref_pts = VLC_TS_INVALID;
304 static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t *p_block )
306 decoder_t *p_dec = p_private;
308 /* Check if we have a picture start code */
309 *pb_ts_used = p_block->p_buffer[3] == 0x00;
311 return ParseMPEGBlock( p_dec, p_block );
315 static int PacketizeValidate( void *p_private, block_t *p_au )
317 decoder_t *p_dec = p_private;
318 decoder_sys_t *p_sys = p_dec->p_sys;
320 /* If a discontinuity has been encountered, then wait till
321 * the next Intra frame before continuing with packetizing */
322 if( unlikely( p_sys->b_discontinuity &&
323 p_sys->b_sync_on_intra_frame ) )
325 if( (p_au->i_flags & BLOCK_FLAG_TYPE_I) == 0 )
327 msg_Dbg( p_dec, "waiting on intra frame" );
330 msg_Dbg( p_dec, "synced on intra frame" );
331 p_sys->b_discontinuity = false;
332 p_au->i_flags |= BLOCK_FLAG_DISCONTINUITY;
335 /* We've just started the stream, wait for the first PTS.
336 * We discard here so we can still get the sequence header. */
337 if( unlikely( p_sys->i_dts <= VLC_TS_INVALID && p_sys->i_pts <= VLC_TS_INVALID &&
338 p_sys->i_interpolated_dts <= VLC_TS_INVALID ))
340 msg_Dbg( p_dec, "need a starting pts/dts" );
344 /* When starting the stream we can have the first frame with
345 * an invalid DTS (i_interpolated_pts is initialized to VLC_TS_INVALID) */
346 if( unlikely( p_au->i_dts <= VLC_TS_INVALID ) )
347 p_au->i_dts = p_au->i_pts;
351 /*****************************************************************************
352 * ParseMPEGBlock: Re-assemble fragments into a block containing a picture
353 *****************************************************************************/
354 static block_t *ParseMPEGBlock( decoder_t *p_dec, block_t *p_frag )
356 decoder_sys_t *p_sys = p_dec->p_sys;
357 block_t *p_pic = NULL;
360 * Check if previous picture is finished
362 if( ( p_sys->b_frame_slice &&
363 (p_frag->p_buffer[3] == 0x00 || p_frag->p_buffer[3] > 0xaf) ) &&
364 p_sys->p_seq == NULL )
366 /* We have a picture but without a sequence header we can't
368 msg_Dbg( p_dec, "waiting for sequence start" );
369 if( p_sys->p_frame ) block_ChainRelease( p_sys->p_frame );
370 p_sys->p_frame = NULL;
371 p_sys->pp_last = &p_sys->p_frame;
372 p_sys->b_frame_slice = false;
375 else if( p_sys->b_frame_slice &&
376 (p_frag->p_buffer[3] == 0x00 || p_frag->p_buffer[3] > 0xaf) )
378 const bool b_eos = p_frag->p_buffer[3] == 0xb7;
384 block_ChainLastAppend( &p_sys->pp_last, p_frag );
388 p_pic = block_ChainGather( p_sys->p_frame );
391 p_pic->i_flags |= BLOCK_FLAG_END_OF_SEQUENCE;
393 i_duration = (mtime_t)( CLOCK_FREQ * p_sys->i_frame_rate_base /
394 p_sys->i_frame_rate );
396 if( !p_sys->b_seq_progressive && p_sys->i_picture_structure != 0x03 )
401 if( p_sys->b_seq_progressive )
403 if( p_sys->i_top_field_first == 0 &&
404 p_sys->i_repeat_first_field == 1 )
408 else if( p_sys->i_top_field_first == 1 &&
409 p_sys->i_repeat_first_field == 1 )
416 if( p_sys->i_picture_structure == 0x03 )
418 if( p_sys->i_progressive_frame && p_sys->i_repeat_first_field )
420 i_duration += i_duration / 2;
425 if( p_sys->b_low_delay || p_sys->i_picture_type == 0x03 )
427 /* Trivial case (DTS == PTS) */
428 /* Correct interpolated dts when we receive a new pts/dts */
429 if( p_sys->i_pts > VLC_TS_INVALID )
430 p_sys->i_interpolated_dts = p_sys->i_pts;
431 if( p_sys->i_dts > VLC_TS_INVALID )
432 p_sys->i_interpolated_dts = p_sys->i_dts;
436 /* Correct interpolated dts when we receive a new pts/dts */
437 if(p_sys->i_last_ref_pts > VLC_TS_INVALID && !p_sys->b_second_field)
438 p_sys->i_interpolated_dts = p_sys->i_last_ref_pts;
439 if( p_sys->i_dts > VLC_TS_INVALID )
440 p_sys->i_interpolated_dts = p_sys->i_dts;
442 if( !p_sys->b_second_field )
443 p_sys->i_last_ref_pts = p_sys->i_pts;
446 p_pic->i_dts = p_sys->i_interpolated_dts;
447 p_sys->i_interpolated_dts += i_duration;
449 /* Set PTS only if we have a B frame or if it comes from the stream */
450 if( p_sys->i_pts > VLC_TS_INVALID )
452 p_pic->i_pts = p_sys->i_pts;
454 else if( p_sys->i_picture_type == 0x03 )
456 p_pic->i_pts = p_pic->i_dts;
460 p_pic->i_pts = VLC_TS_INVALID;
463 switch ( p_sys->i_picture_type )
466 p_pic->i_flags |= BLOCK_FLAG_TYPE_I;
469 p_pic->i_flags |= BLOCK_FLAG_TYPE_P;
472 p_pic->i_flags |= BLOCK_FLAG_TYPE_B;
476 p_pic->i_length = p_sys->i_interpolated_dts - p_pic->i_dts;
479 msg_Dbg( p_dec, "pic: type=%d dts=%"PRId64" pts-dts=%"PRId64,
480 p_sys->i_picture_type, p_pic->i_dts, p_pic->i_pts - p_pic->i_dts);
484 p_sys->p_frame = NULL;
485 p_sys->pp_last = &p_sys->p_frame;
486 p_sys->b_frame_slice = false;
488 if( p_sys->i_picture_structure != 0x03 )
490 p_sys->b_second_field = !p_sys->b_second_field;
494 p_sys->b_second_field = 0;
498 p_sys->b_cc_reset = true;
499 p_sys->i_cc_pts = p_pic->i_pts;
500 p_sys->i_cc_dts = p_pic->i_dts;
501 p_sys->i_cc_flags = p_pic->i_flags;
504 if( !p_pic && p_sys->b_cc_reset )
506 p_sys->b_cc_reset = false;
507 cc_Flush( &p_sys->cc );
513 * Check info of current fragment
515 if( p_frag->p_buffer[3] == 0xb8 )
517 /* Group start code */
519 p_sys->i_seq_old > p_sys->i_frame_rate/p_sys->i_frame_rate_base )
521 /* Useful for mpeg1: repeat sequence header every second */
522 block_ChainLastAppend( &p_sys->pp_last, block_Duplicate( p_sys->p_seq ) );
525 block_ChainLastAppend( &p_sys->pp_last, block_Duplicate( p_sys->p_ext ) );
528 p_sys->i_seq_old = 0;
531 else if( p_frag->p_buffer[3] == 0xb3 && p_frag->i_buffer >= 8 )
533 /* Sequence header code */
534 static const int code_to_frame_rate[16][2] =
536 { 1, 1 }, /* invalid */
537 { 24000, 1001 }, { 24, 1 }, { 25, 1 }, { 30000, 1001 },
538 { 30, 1 }, { 50, 1 }, { 60000, 1001 }, { 60, 1 },
539 /* Unofficial 15fps from Xing*/
541 /* Unofficial economy rates from libmpeg3 */
542 { 5000, 1001 }, { 1000, 1001 }, { 12000, 1001 }, { 15000, 1001 },
543 { 1, 1 }, { 1, 1 } /* invalid */
546 if( p_sys->p_seq ) block_Release( p_sys->p_seq );
547 if( p_sys->p_ext ) block_Release( p_sys->p_ext );
549 p_sys->p_seq = block_Duplicate( p_frag );
550 p_sys->i_seq_old = 0;
553 p_dec->fmt_out.video.i_width =
554 ( p_frag->p_buffer[4] << 4)|(p_frag->p_buffer[5] >> 4 );
555 p_dec->fmt_out.video.i_height =
556 ( (p_frag->p_buffer[5]&0x0f) << 8 )|p_frag->p_buffer[6];
557 p_sys->i_aspect_ratio_info = p_frag->p_buffer[7] >> 4;
559 /* TODO: MPEG1 aspect ratio */
561 p_sys->i_frame_rate = code_to_frame_rate[p_frag->p_buffer[7]&0x0f][0];
562 p_sys->i_frame_rate_base =
563 code_to_frame_rate[p_frag->p_buffer[7]&0x0f][1];
565 p_dec->fmt_out.video.i_frame_rate = p_sys->i_frame_rate;
566 p_dec->fmt_out.video.i_frame_rate_base = p_sys->i_frame_rate_base;
568 p_sys->b_seq_progressive = true;
569 p_sys->b_low_delay = true;
571 if ( !p_sys->b_inited )
573 msg_Dbg( p_dec, "size %dx%d fps=%.3f",
574 p_dec->fmt_out.video.i_width, p_dec->fmt_out.video.i_height,
575 p_sys->i_frame_rate / (float)p_sys->i_frame_rate_base );
579 else if( p_frag->p_buffer[3] == 0xb5 )
581 int i_type = p_frag->p_buffer[4] >> 4;
583 /* Extension start code */
587 static const int mpeg2_aspect[16][2] =
589 {0,1}, {1,1}, {4,3}, {16,9}, {221,100},
590 {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1},
595 /* sequence extension */
596 if( p_sys->p_ext) block_Release( p_sys->p_ext );
597 p_sys->p_ext = block_Duplicate( p_frag );
599 if( p_frag->i_buffer >= 10 )
601 p_sys->b_seq_progressive =
602 p_frag->p_buffer[5]&0x08 ? true : false;
604 p_frag->p_buffer[9]&0x80 ? true : false;
607 /* Do not set aspect ratio : in case we're transcoding,
608 * transcode will take our fmt_out as a fmt_in to libmpeg2.
609 * libmpeg2.c will then believe that the user has requested
610 * a specific aspect ratio, which she hasn't. Thus in case
611 * of aspect ratio change, we're screwed. --Meuuh
614 p_dec->fmt_out.video.i_sar_num =
615 mpeg2_aspect[p_sys->i_aspect_ratio_info][0] *
616 p_dec->fmt_out.video.i_height;
617 p_dec->fmt_out.video.i_sar_den =
618 mpeg2_aspect[p_sys->i_aspect_ratio_info][1] *
619 p_dec->fmt_out.video.i_width;
623 else if( i_type == 0x08 )
625 /* picture extension */
626 p_sys->i_picture_structure = p_frag->p_buffer[6]&0x03;
627 p_sys->i_top_field_first = p_frag->p_buffer[7] >> 7;
628 p_sys->i_repeat_first_field= (p_frag->p_buffer[7]>>1)&0x01;
629 p_sys->i_progressive_frame = p_frag->p_buffer[8] >> 7;
632 else if( p_frag->p_buffer[3] == 0xb2 && p_frag->i_buffer > 4 )
634 cc_Extract( &p_sys->cc, p_sys->i_top_field_first,
635 &p_frag->p_buffer[4], p_frag->i_buffer - 4 );
637 else if( p_frag->p_buffer[3] == 0x00 )
639 /* Picture start code */
642 if( p_frag->i_buffer >= 6 )
644 p_sys->i_temporal_ref =
645 ( p_frag->p_buffer[4] << 2 )|(p_frag->p_buffer[5] >> 6);
646 p_sys->i_picture_type = ( p_frag->p_buffer[5] >> 3 ) & 0x03;
649 p_sys->i_dts = p_frag->i_dts;
650 p_sys->i_pts = p_frag->i_pts;
652 else if( p_frag->p_buffer[3] >= 0x01 && p_frag->p_buffer[3] <= 0xaf )
654 /* Slice start code */
655 p_sys->b_frame_slice = true;
658 /* Append the block */
659 block_ChainLastAppend( &p_sys->pp_last, p_frag );