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
;
162 p_dec
->pf_packetize
= Packetize
;
163 p_dec
->pf_get_cc
= GetCc
;
165 p_dec
->p_sys
= p_sys
= malloc( sizeof( decoder_sys_t
) );
168 memset( p_dec
->p_sys
, 0, sizeof( decoder_sys_t
) );
171 packetizer_Init( &p_sys
->packetizer
,
172 p_mp2v_startcode
, sizeof(p_mp2v_startcode
),
174 PacketizeReset
, PacketizeParse
, PacketizeValidate
, p_dec
);
178 p_sys
->p_frame
= NULL
;
179 p_sys
->pp_last
= &p_sys
->p_frame
;
180 p_sys
->b_frame_slice
= false;
182 p_sys
->i_dts
= p_sys
->i_pts
= VLC_TS_INVALID
;
184 p_sys
->i_frame_rate
= 1;
185 p_sys
->i_frame_rate_base
= 1;
186 p_sys
->b_seq_progressive
= true;
187 p_sys
->b_low_delay
= true;
188 p_sys
->i_seq_old
= 0;
190 p_sys
->i_temporal_ref
= 0;
191 p_sys
->i_picture_type
= 0;
192 p_sys
->i_picture_structure
= 0x03; /* frame */
193 p_sys
->i_top_field_first
= 0;
194 p_sys
->i_repeat_first_field
= 0;
195 p_sys
->i_progressive_frame
= 0;
198 p_sys
->i_interpolated_dts
= VLC_TS_INVALID
;
199 p_sys
->i_last_ref_pts
= VLC_TS_INVALID
;
200 p_sys
->b_second_field
= 0;
202 p_sys
->b_discontinuity
= false;
203 p_sys
->b_sync_on_intra_frame
= var_CreateGetBool( p_dec
, "packetizer-mpegvideo-sync-iframe" );
204 if( p_sys
->b_sync_on_intra_frame
)
205 msg_Dbg( p_dec
, "syncing on intra frame now" );
207 p_sys
->b_cc_reset
= false;
210 p_sys
->i_cc_flags
= 0;
211 cc_Init( &p_sys
->cc
);
216 /*****************************************************************************
218 *****************************************************************************/
219 static void Close( vlc_object_t
*p_this
)
221 decoder_t
*p_dec
= (decoder_t
*)p_this
;
222 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
226 block_Release( p_sys
->p_seq
);
230 block_Release( p_sys
->p_ext
);
234 block_ChainRelease( p_sys
->p_frame
);
236 packetizer_Clean( &p_sys
->packetizer
);
238 var_Destroy( p_dec
, "packetizer-mpegvideo-sync-iframe" );
243 /*****************************************************************************
245 *****************************************************************************/
246 static block_t
*Packetize( decoder_t
*p_dec
, block_t
**pp_block
)
248 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
250 return packetizer_Packetize( &p_sys
->packetizer
, pp_block
);
253 /*****************************************************************************
255 *****************************************************************************/
256 static block_t
*GetCc( decoder_t
*p_dec
, bool pb_present
[4] )
258 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
262 for( i
= 0; i
< 4; i
++ )
263 pb_present
[i
] = p_sys
->cc
.pb_present
[i
];
265 if( p_sys
->cc
.i_data
<= 0 )
268 p_cc
= block_Alloc( p_sys
->cc
.i_data
);
271 memcpy( p_cc
->p_buffer
, p_sys
->cc
.p_data
, p_sys
->cc
.i_data
);
273 p_cc
->i_pts
= p_sys
->cc
.b_reorder
? p_sys
->i_cc_pts
: p_sys
->i_cc_dts
;
274 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
);
276 cc_Flush( &p_sys
->cc
);
280 /*****************************************************************************
282 *****************************************************************************/
283 static void PacketizeReset( void *p_private
, bool b_broken
)
285 decoder_t
*p_dec
= p_private
;
286 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
290 p_sys
->b_discontinuity
= true;
292 block_ChainRelease( p_sys
->p_frame
);
293 p_sys
->p_frame
= NULL
;
294 p_sys
->pp_last
= &p_sys
->p_frame
;
295 p_sys
->b_frame_slice
= false;
299 p_sys
->i_interpolated_dts
=
300 p_sys
->i_last_ref_pts
= VLC_TS_INVALID
;
303 static block_t
*PacketizeParse( void *p_private
, bool *pb_ts_used
, block_t
*p_block
)
305 decoder_t
*p_dec
= p_private
;
307 /* Check if we have a picture start code */
308 *pb_ts_used
= p_block
->p_buffer
[3] == 0x00;
310 return ParseMPEGBlock( p_dec
, p_block
);
314 static int PacketizeValidate( void *p_private
, block_t
*p_au
)
316 decoder_t
*p_dec
= p_private
;
317 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
319 /* If a discontinuity has been encountered, then wait till
320 * the next Intra frame before continuing with packetizing */
321 if( p_sys
->b_discontinuity
&&
322 p_sys
->b_sync_on_intra_frame
)
324 if( (p_au
->i_flags
& BLOCK_FLAG_TYPE_I
) == 0 )
326 msg_Dbg( p_dec
, "waiting on intra frame" );
329 msg_Dbg( p_dec
, "synced on intra frame" );
330 p_sys
->b_discontinuity
= false;
331 p_au
->i_flags
|= BLOCK_FLAG_DISCONTINUITY
;
334 /* We've just started the stream, wait for the first PTS.
335 * We discard here so we can still get the sequence header. */
336 if( p_sys
->i_dts
<= VLC_TS_INVALID
&& p_sys
->i_pts
<= VLC_TS_INVALID
&&
337 p_sys
->i_interpolated_dts
<= VLC_TS_INVALID
)
339 msg_Dbg( p_dec
, "need a starting pts/dts" );
343 /* When starting the stream we can have the first frame with
344 * an invalid DTS (i_interpolated_pts is initialized to VLC_TS_INVALID) */
345 if( p_au
->i_dts
<= VLC_TS_INVALID
)
346 p_au
->i_dts
= p_au
->i_pts
;
350 /*****************************************************************************
351 * ParseMPEGBlock: Re-assemble fragments into a block containing a picture
352 *****************************************************************************/
353 static block_t
*ParseMPEGBlock( decoder_t
*p_dec
, block_t
*p_frag
)
355 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
356 block_t
*p_pic
= NULL
;
359 * Check if previous picture is finished
361 if( ( p_sys
->b_frame_slice
&&
362 (p_frag
->p_buffer
[3] == 0x00 || p_frag
->p_buffer
[3] > 0xaf) ) &&
363 p_sys
->p_seq
== NULL
)
365 /* We have a picture but without a sequence header we can't
367 msg_Dbg( p_dec
, "waiting for sequence start" );
368 if( p_sys
->p_frame
) block_ChainRelease( p_sys
->p_frame
);
369 p_sys
->p_frame
= NULL
;
370 p_sys
->pp_last
= &p_sys
->p_frame
;
371 p_sys
->b_frame_slice
= false;
374 else if( p_sys
->b_frame_slice
&&
375 (p_frag
->p_buffer
[3] == 0x00 || p_frag
->p_buffer
[3] > 0xaf) )
377 const bool b_eos
= p_frag
->p_buffer
[3] == 0xb7;
383 block_ChainLastAppend( &p_sys
->pp_last
, p_frag
);
387 p_pic
= block_ChainGather( p_sys
->p_frame
);
390 p_pic
->i_flags
|= BLOCK_FLAG_END_OF_SEQUENCE
;
392 i_duration
= (mtime_t
)( CLOCK_FREQ
* p_sys
->i_frame_rate_base
/
393 p_sys
->i_frame_rate
);
395 if( !p_sys
->b_seq_progressive
&& p_sys
->i_picture_structure
!= 0x03 )
400 if( p_sys
->b_seq_progressive
)
402 if( p_sys
->i_top_field_first
== 0 &&
403 p_sys
->i_repeat_first_field
== 1 )
407 else if( p_sys
->i_top_field_first
== 1 &&
408 p_sys
->i_repeat_first_field
== 1 )
415 if( p_sys
->i_picture_structure
== 0x03 )
417 if( p_sys
->i_progressive_frame
&& p_sys
->i_repeat_first_field
)
419 i_duration
+= i_duration
/ 2;
424 if( p_sys
->b_low_delay
|| p_sys
->i_picture_type
== 0x03 )
426 /* Trivial case (DTS == PTS) */
427 /* Correct interpolated dts when we receive a new pts/dts */
428 if( p_sys
->i_pts
> VLC_TS_INVALID
)
429 p_sys
->i_interpolated_dts
= p_sys
->i_pts
;
430 if( p_sys
->i_dts
> VLC_TS_INVALID
)
431 p_sys
->i_interpolated_dts
= p_sys
->i_dts
;
435 /* Correct interpolated dts when we receive a new pts/dts */
436 if(p_sys
->i_last_ref_pts
> VLC_TS_INVALID
&& !p_sys
->b_second_field
)
437 p_sys
->i_interpolated_dts
= p_sys
->i_last_ref_pts
;
438 if( p_sys
->i_dts
> VLC_TS_INVALID
)
439 p_sys
->i_interpolated_dts
= p_sys
->i_dts
;
441 if( !p_sys
->b_second_field
)
442 p_sys
->i_last_ref_pts
= p_sys
->i_pts
;
445 p_pic
->i_dts
= p_sys
->i_interpolated_dts
;
446 p_sys
->i_interpolated_dts
+= i_duration
;
448 /* Set PTS only if we have a B frame or if it comes from the stream */
449 if( p_sys
->i_pts
> VLC_TS_INVALID
)
451 p_pic
->i_pts
= p_sys
->i_pts
;
453 else if( p_sys
->i_picture_type
== 0x03 )
455 p_pic
->i_pts
= p_pic
->i_dts
;
459 p_pic
->i_pts
= VLC_TS_INVALID
;
462 switch ( p_sys
->i_picture_type
)
465 p_pic
->i_flags
|= BLOCK_FLAG_TYPE_I
;
468 p_pic
->i_flags
|= BLOCK_FLAG_TYPE_P
;
471 p_pic
->i_flags
|= BLOCK_FLAG_TYPE_B
;
475 p_pic
->i_length
= p_sys
->i_interpolated_dts
- p_pic
->i_dts
;
478 msg_Dbg( p_dec
, "pic: type=%d dts=%"PRId64
" pts-dts=%"PRId64
,
479 p_sys
->i_picture_type
, p_pic
->i_dts
, p_pic
->i_pts
- p_pic
->i_dts
);
483 p_sys
->p_frame
= NULL
;
484 p_sys
->pp_last
= &p_sys
->p_frame
;
485 p_sys
->b_frame_slice
= false;
487 if( p_sys
->i_picture_structure
!= 0x03 )
489 p_sys
->b_second_field
= !p_sys
->b_second_field
;
493 p_sys
->b_second_field
= 0;
497 p_sys
->b_cc_reset
= true;
498 p_sys
->i_cc_pts
= p_pic
->i_pts
;
499 p_sys
->i_cc_dts
= p_pic
->i_dts
;
500 p_sys
->i_cc_flags
= p_pic
->i_flags
;
503 if( !p_pic
&& p_sys
->b_cc_reset
)
505 p_sys
->b_cc_reset
= false;
506 cc_Flush( &p_sys
->cc
);
512 * Check info of current fragment
514 if( p_frag
->p_buffer
[3] == 0xb8 )
516 /* Group start code */
518 p_sys
->i_seq_old
> p_sys
->i_frame_rate
/p_sys
->i_frame_rate_base
)
520 /* Useful for mpeg1: repeat sequence header every second */
521 block_ChainLastAppend( &p_sys
->pp_last
, block_Duplicate( p_sys
->p_seq
) );
524 block_ChainLastAppend( &p_sys
->pp_last
, block_Duplicate( p_sys
->p_ext
) );
527 p_sys
->i_seq_old
= 0;
530 else if( p_frag
->p_buffer
[3] == 0xb3 && p_frag
->i_buffer
>= 8 )
532 /* Sequence header code */
533 static const int code_to_frame_rate
[16][2] =
535 { 1, 1 }, /* invalid */
536 { 24000, 1001 }, { 24, 1 }, { 25, 1 }, { 30000, 1001 },
537 { 30, 1 }, { 50, 1 }, { 60000, 1001 }, { 60, 1 },
538 /* Unofficial 15fps from Xing*/
540 /* Unofficial economy rates from libmpeg3 */
541 { 5000, 1001 }, { 1000, 1001 }, { 12000, 1001 }, { 15000, 1001 },
542 { 1, 1 }, { 1, 1 } /* invalid */
545 if( p_sys
->p_seq
) block_Release( p_sys
->p_seq
);
546 if( p_sys
->p_ext
) block_Release( p_sys
->p_ext
);
548 p_sys
->p_seq
= block_Duplicate( p_frag
);
549 p_sys
->i_seq_old
= 0;
552 p_dec
->fmt_out
.video
.i_width
=
553 ( p_frag
->p_buffer
[4] << 4)|(p_frag
->p_buffer
[5] >> 4 );
554 p_dec
->fmt_out
.video
.i_height
=
555 ( (p_frag
->p_buffer
[5]&0x0f) << 8 )|p_frag
->p_buffer
[6];
556 p_sys
->i_aspect_ratio_info
= p_frag
->p_buffer
[7] >> 4;
558 /* TODO: MPEG1 aspect ratio */
560 p_sys
->i_frame_rate
= code_to_frame_rate
[p_frag
->p_buffer
[7]&0x0f][0];
561 p_sys
->i_frame_rate_base
=
562 code_to_frame_rate
[p_frag
->p_buffer
[7]&0x0f][1];
564 p_dec
->fmt_out
.video
.i_frame_rate
= p_sys
->i_frame_rate
;
565 p_dec
->fmt_out
.video
.i_frame_rate_base
= p_sys
->i_frame_rate_base
;
567 p_sys
->b_seq_progressive
= true;
568 p_sys
->b_low_delay
= true;
570 if ( !p_sys
->b_inited
)
572 msg_Dbg( p_dec
, "size %dx%d fps=%.3f",
573 p_dec
->fmt_out
.video
.i_width
, p_dec
->fmt_out
.video
.i_height
,
574 p_sys
->i_frame_rate
/ (float)p_sys
->i_frame_rate_base
);
578 else if( p_frag
->p_buffer
[3] == 0xb5 )
580 int i_type
= p_frag
->p_buffer
[4] >> 4;
582 /* Extension start code */
586 static const int mpeg2_aspect
[16][2] =
588 {0,1}, {1,1}, {4,3}, {16,9}, {221,100},
589 {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1},
594 /* sequence extension */
595 if( p_sys
->p_ext
) block_Release( p_sys
->p_ext
);
596 p_sys
->p_ext
= block_Duplicate( p_frag
);
598 if( p_frag
->i_buffer
>= 10 )
600 p_sys
->b_seq_progressive
=
601 p_frag
->p_buffer
[5]&0x08 ? true : false;
603 p_frag
->p_buffer
[9]&0x80 ? true : false;
606 /* Do not set aspect ratio : in case we're transcoding,
607 * transcode will take our fmt_out as a fmt_in to libmpeg2.
608 * libmpeg2.c will then believe that the user has requested
609 * a specific aspect ratio, which she hasn't. Thus in case
610 * of aspect ratio change, we're screwed. --Meuuh
613 p_dec
->fmt_out
.video
.i_sar_num
=
614 mpeg2_aspect
[p_sys
->i_aspect_ratio_info
][0] *
615 p_dec
->fmt_out
.video
.i_height
;
616 p_dec
->fmt_out
.video
.i_sar_den
=
617 mpeg2_aspect
[p_sys
->i_aspect_ratio_info
][1] *
618 p_dec
->fmt_out
.video
.i_width
;
622 else if( i_type
== 0x08 )
624 /* picture extension */
625 p_sys
->i_picture_structure
= p_frag
->p_buffer
[6]&0x03;
626 p_sys
->i_top_field_first
= p_frag
->p_buffer
[7] >> 7;
627 p_sys
->i_repeat_first_field
= (p_frag
->p_buffer
[7]>>1)&0x01;
628 p_sys
->i_progressive_frame
= p_frag
->p_buffer
[8] >> 7;
631 else if( p_frag
->p_buffer
[3] == 0xb2 && p_frag
->i_buffer
> 4 )
633 cc_Extract( &p_sys
->cc
, p_sys
->i_top_field_first
,
634 &p_frag
->p_buffer
[4], p_frag
->i_buffer
- 4 );
636 else if( p_frag
->p_buffer
[3] == 0x00 )
638 /* Picture start code */
641 if( p_frag
->i_buffer
>= 6 )
643 p_sys
->i_temporal_ref
=
644 ( p_frag
->p_buffer
[4] << 2 )|(p_frag
->p_buffer
[5] >> 6);
645 p_sys
->i_picture_type
= ( p_frag
->p_buffer
[5] >> 3 ) & 0x03;
648 p_sys
->i_dts
= p_frag
->i_dts
;
649 p_sys
->i_pts
= p_frag
->i_pts
;
651 else if( p_frag
->p_buffer
[3] >= 0x01 && p_frag
->p_buffer
[3] <= 0xaf )
653 /* Slice start code */
654 p_sys
->b_frame_slice
= true;
657 /* Append the block */
658 block_ChainLastAppend( &p_sys
->pp_last
, p_frag
);