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"
56 #include "startcode_helper.h"
60 #define SYNC_INTRAFRAME_TEXT N_("Sync on Intra Frame")
61 #define SYNC_INTRAFRAME_LONGTEXT N_("Normally the packetizer would " \
62 "sync on the next full frame. This flags instructs the packetizer " \
63 "to sync on the first Intra Frame found.")
65 /*****************************************************************************
67 *****************************************************************************/
68 static int Open ( vlc_object_t
* );
69 static void Close( vlc_object_t
* );
72 set_category( CAT_SOUT
)
73 set_subcategory( SUBCAT_SOUT_PACKETIZER
)
74 set_description( N_("MPEG-I/II video packetizer") )
75 set_shortname( N_("MPEG Video") )
76 set_capability( "packetizer", 50 )
77 set_callbacks( Open
, Close
)
79 add_bool( "packetizer-mpegvideo-sync-iframe", false, SYNC_INTRAFRAME_TEXT
,
80 SYNC_INTRAFRAME_LONGTEXT
, true )
85 PICTURE_STARTCODE
= 0x00,
86 SLICE_STARTCODE_FIRST
= 0x01,
87 SLICE_STARTCODE_LAST
= 0xAF,
88 USER_DATA_STARTCODE
= 0xB2,
89 SEQUENCE_HEADER_STARTCODE
= 0xB3,
90 SEQUENCE_ERROR_STARTCODE
= 0xB4,
91 EXTENSION_STARTCODE
= 0xB5,
92 SEQUENCE_END_STARTCODE
= 0xB7,
93 GROUP_STARTCODE
= 0xB8,
94 SYSTEM_STARTCODE_FIRST
= 0xB9,
95 SYSTEM_STARTCODE_LAST
= 0xFF,
98 enum extension_start_code_identifier_e
100 SEQUENCE_EXTENSION_ID
= 0x01,
101 SEQUENCE_DISPLAY_EXTENSION_ID
= 0x02,
102 QUANT_MATRIX_EXTENSION_ID
= 0x03,
103 COPYRIGHT_EXTENSION_ID
= 0x04,
104 SEQUENCE_SCALABLE_EXTENSION_ID
= 0x05,
105 PICTURE_DISPLAY_EXTENSION_ID
= 0x07,
106 PICTURE_CODING_EXTENSION_ID
= 0x08,
107 PICTURE_SPATIAL_SCALABLE_EXTENSION_ID
= 0x09,
108 PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID
= 0x0A,
109 CAMERA_PARAMETERS_EXTENSION_ID
= 0x0B,
110 ITU_T_EXTENSION_ID
= 0x0C,
113 /*****************************************************************************
115 *****************************************************************************/
121 packetizer_t packetizer
;
123 /* Sequence header and extension */
127 /* Current frame being built */
136 date_t prev_iframe_dts
;
138 /* Sequence properties */
139 unsigned i_frame_rate
;
140 unsigned i_frame_rate_base
;
141 bool b_seq_progressive
;
143 int i_aspect_ratio_info
;
146 /* Picture properties */
148 int i_prev_temporal_ref
;
150 int i_picture_structure
;
151 int i_top_field_first
;
152 int i_repeat_first_field
;
153 int i_progressive_frame
;
155 mtime_t i_last_ref_pts
;
157 mtime_t i_last_frame_pts
;
158 uint16_t i_last_frame_refid
;
162 /* Number of pictures since last sequence header */
166 bool b_sync_on_intra_frame
;
167 bool b_waiting_iframe
;
168 int i_next_block_flags
;
178 static block_t
*Packetize( decoder_t
*, block_t
** );
179 static void PacketizeFlush( decoder_t
* );
180 static block_t
*GetCc( decoder_t
*p_dec
, bool pb_present
[4], int * );
182 static void PacketizeReset( void *p_private
, bool b_broken
);
183 static block_t
*PacketizeParse( void *p_private
, bool *pb_ts_used
, block_t
* );
184 static int PacketizeValidate( void *p_private
, block_t
* );
186 static block_t
*ParseMPEGBlock( decoder_t
*, block_t
* );
188 static const uint8_t p_mp2v_startcode
[3] = { 0x00, 0x00, 0x01 };
190 /*****************************************************************************
192 *****************************************************************************/
193 static int Open( vlc_object_t
*p_this
)
195 decoder_t
*p_dec
= (decoder_t
*)p_this
;
196 decoder_sys_t
*p_sys
;
198 if( p_dec
->fmt_in
.i_codec
!= VLC_CODEC_MPGV
)
201 p_dec
->p_sys
= p_sys
= malloc( sizeof( decoder_sys_t
) );
204 memset( p_dec
->p_sys
, 0, sizeof( decoder_sys_t
) );
206 p_dec
->fmt_out
.i_codec
= VLC_CODEC_MPGV
;
207 p_dec
->fmt_out
.i_original_fourcc
= p_dec
->fmt_in
.i_original_fourcc
;
210 packetizer_Init( &p_sys
->packetizer
,
211 p_mp2v_startcode
, sizeof(p_mp2v_startcode
), startcode_FindAnnexB
,
213 PacketizeReset
, PacketizeParse
, PacketizeValidate
, p_dec
);
217 p_sys
->p_frame
= NULL
;
218 p_sys
->pp_last
= &p_sys
->p_frame
;
219 p_sys
->b_frame_slice
= false;
222 p_sys
->i_pts
= VLC_TS_INVALID
;
223 date_Init( &p_sys
->dts
, 30000, 1001 );
224 date_Set( &p_sys
->dts
, VLC_TS_INVALID
);
225 date_Init( &p_sys
->prev_iframe_dts
, 30000, 1001 );
226 date_Set( &p_sys
->prev_iframe_dts
, VLC_TS_INVALID
);
228 p_sys
->i_frame_rate
= 2 * 30000;
229 p_sys
->i_frame_rate_base
= 1001;
230 p_sys
->b_seq_progressive
= true;
231 p_sys
->b_low_delay
= true;
232 p_sys
->i_seq_old
= 0;
234 p_sys
->i_temporal_ref
= 0;
235 p_sys
->i_prev_temporal_ref
= 2048;
236 p_sys
->i_picture_type
= 0;
237 p_sys
->i_picture_structure
= 0x03; /* frame */
238 p_sys
->i_top_field_first
= 0;
239 p_sys
->i_repeat_first_field
= 0;
240 p_sys
->i_progressive_frame
= 0;
243 p_sys
->i_last_ref_pts
= VLC_TS_INVALID
;
244 p_sys
->b_second_field
= 0;
246 p_sys
->i_next_block_flags
= 0;
248 p_sys
->i_last_frame_refid
= 0;
250 p_sys
->b_waiting_iframe
=
251 p_sys
->b_sync_on_intra_frame
= var_CreateGetBool( p_dec
, "packetizer-mpegvideo-sync-iframe" );
252 if( p_sys
->b_sync_on_intra_frame
)
253 msg_Dbg( p_dec
, "syncing on intra frame now" );
255 p_sys
->b_cc_reset
= false;
258 p_sys
->i_cc_flags
= 0;
259 cc_Init( &p_sys
->cc
);
261 p_dec
->pf_packetize
= Packetize
;
262 p_dec
->pf_flush
= PacketizeFlush
;
263 p_dec
->pf_get_cc
= GetCc
;
268 /*****************************************************************************
270 *****************************************************************************/
271 static void Close( vlc_object_t
*p_this
)
273 decoder_t
*p_dec
= (decoder_t
*)p_this
;
274 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
278 block_Release( p_sys
->p_seq
);
282 block_Release( p_sys
->p_ext
);
286 block_ChainRelease( p_sys
->p_frame
);
288 packetizer_Clean( &p_sys
->packetizer
);
290 var_Destroy( p_dec
, "packetizer-mpegvideo-sync-iframe" );
295 /*****************************************************************************
297 *****************************************************************************/
298 static block_t
*Packetize( decoder_t
*p_dec
, block_t
**pp_block
)
300 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
302 return packetizer_Packetize( &p_sys
->packetizer
, pp_block
);
305 static void PacketizeFlush( decoder_t
*p_dec
)
307 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
309 packetizer_Flush( &p_sys
->packetizer
);
312 /*****************************************************************************
314 *****************************************************************************/
315 static block_t
*GetCc( decoder_t
*p_dec
, bool pb_present
[4], int *pi_reorder_depth
)
317 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
320 *pi_reorder_depth
= p_sys
->cc
.b_reorder
? 0 : -1;
322 for( i
= 0; i
< 4; i
++ )
323 pb_present
[i
] = p_sys
->cc
.pb_present
[i
];
325 if( !p_sys
->cc
.b_reorder
&& p_sys
->cc
.i_data
<= 0 )
328 p_cc
= block_Alloc( p_sys
->cc
.i_data
);
331 memcpy( p_cc
->p_buffer
, p_sys
->cc
.p_data
, p_sys
->cc
.i_data
);
333 p_cc
->i_pts
= p_sys
->cc
.b_reorder
? p_sys
->i_cc_pts
: p_sys
->i_cc_dts
;
334 p_cc
->i_flags
= p_sys
->i_cc_flags
& BLOCK_FLAG_TYPE_MASK
;
336 cc_Flush( &p_sys
->cc
);
340 /*****************************************************************************
342 *****************************************************************************/
343 static void PacketizeReset( void *p_private
, bool b_broken
)
345 VLC_UNUSED(b_broken
);
346 decoder_t
*p_dec
= p_private
;
347 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
349 p_sys
->i_next_block_flags
= BLOCK_FLAG_DISCONTINUITY
;
352 block_ChainRelease( p_sys
->p_frame
);
353 p_sys
->p_frame
= NULL
;
354 p_sys
->pp_last
= &p_sys
->p_frame
;
355 p_sys
->b_frame_slice
= false;
357 date_Set( &p_sys
->dts
, VLC_TS_INVALID
);
358 date_Set( &p_sys
->prev_iframe_dts
, VLC_TS_INVALID
);
361 p_sys
->i_last_ref_pts
= VLC_TS_INVALID
;
362 p_sys
->b_waiting_iframe
= p_sys
->b_sync_on_intra_frame
;
363 p_sys
->i_prev_temporal_ref
= 2048;
366 static block_t
*PacketizeParse( void *p_private
, bool *pb_ts_used
, block_t
*p_block
)
368 decoder_t
*p_dec
= p_private
;
369 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
371 /* Check if we have a picture start code */
372 *pb_ts_used
= p_block
->p_buffer
[3] == PICTURE_STARTCODE
;
374 p_block
= ParseMPEGBlock( p_dec
, p_block
);
377 p_block
->i_flags
|= p_sys
->i_next_block_flags
;
378 p_sys
->i_next_block_flags
= 0;
384 static int PacketizeValidate( void *p_private
, block_t
*p_au
)
386 decoder_t
*p_dec
= p_private
;
387 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
389 if( unlikely( p_sys
->b_waiting_iframe
) )
391 if( (p_au
->i_flags
& BLOCK_FLAG_TYPE_I
) == 0 )
393 msg_Dbg( p_dec
, "waiting on intra frame" );
396 msg_Dbg( p_dec
, "synced on intra frame" );
397 p_sys
->b_waiting_iframe
= false;
400 /* We've just started the stream, wait for the first PTS.
401 * We discard here so we can still get the sequence header. */
402 if( unlikely( p_sys
->i_dts
<= VLC_TS_INVALID
&& p_sys
->i_pts
<= VLC_TS_INVALID
&&
403 date_Get( &p_sys
->dts
) <= VLC_TS_INVALID
))
405 msg_Dbg( p_dec
, "need a starting pts/dts" );
409 /* When starting the stream we can have the first frame with
410 * an invalid DTS (i_interpolated_pts is initialized to VLC_TS_INVALID) */
411 if( unlikely( p_au
->i_dts
<= VLC_TS_INVALID
) )
412 p_au
->i_dts
= p_au
->i_pts
;
416 /*****************************************************************************
417 * ParseMPEGBlock: Re-assemble fragments into a block containing a picture
418 *****************************************************************************/
419 static block_t
*ParseMPEGBlock( decoder_t
*p_dec
, block_t
*p_frag
)
421 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
422 block_t
*p_pic
= NULL
;
424 const enum mpeg_startcode_e startcode
= p_frag
->p_buffer
[3];
426 * Check if previous picture is finished
428 if( ( p_sys
->b_frame_slice
&&
429 (startcode
== PICTURE_STARTCODE
|| startcode
> SLICE_STARTCODE_LAST
) ) &&
430 p_sys
->p_seq
== NULL
)
432 /* We have a picture but without a sequence header we can't
434 msg_Dbg( p_dec
, "waiting for sequence start" );
435 if( p_sys
->p_frame
) block_ChainRelease( p_sys
->p_frame
);
436 p_sys
->p_frame
= NULL
;
437 p_sys
->pp_last
= &p_sys
->p_frame
;
438 p_sys
->b_frame_slice
= false;
441 else if( p_sys
->b_frame_slice
&&
442 (startcode
== PICTURE_STARTCODE
||
443 (startcode
> SLICE_STARTCODE_LAST
&& startcode
!= EXTENSION_STARTCODE
)) )
445 const bool b_eos
= startcode
== SEQUENCE_END_STARTCODE
;
449 block_ChainLastAppend( &p_sys
->pp_last
, p_frag
);
453 p_pic
= block_ChainGather( p_sys
->p_frame
);
458 p_pic
->i_flags
|= BLOCK_FLAG_END_OF_SEQUENCE
;
460 unsigned i_num_fields
;
462 if( !p_sys
->b_seq_progressive
&& p_sys
->i_picture_structure
!= 0x03 /* Field Picture */ )
467 if( p_sys
->b_seq_progressive
)
469 if( p_sys
->i_top_field_first
== 0 &&
470 p_sys
->i_repeat_first_field
== 1 )
474 else if( p_sys
->i_top_field_first
== 1 &&
475 p_sys
->i_repeat_first_field
== 1 )
482 if( p_sys
->i_picture_structure
== 0x03 /* Frame Picture */ )
484 if( p_sys
->i_progressive_frame
&& p_sys
->i_repeat_first_field
)
491 switch ( p_sys
->i_picture_type
)
494 p_pic
->i_flags
|= BLOCK_FLAG_TYPE_I
;
497 p_pic
->i_flags
|= BLOCK_FLAG_TYPE_P
;
500 p_pic
->i_flags
|= BLOCK_FLAG_TYPE_B
;
504 if( !p_sys
->b_seq_progressive
)
506 if( p_sys
->i_picture_structure
< 0x03 )
508 p_pic
->i_flags
|= BLOCK_FLAG_SINGLE_FIELD
;
509 p_pic
->i_flags
|= (p_sys
->i_picture_structure
== 0x01) ? BLOCK_FLAG_TOP_FIELD_FIRST
510 : BLOCK_FLAG_BOTTOM_FIELD_FIRST
;
512 else /* if( p_sys->i_picture_structure == 0x03 ) */
514 p_pic
->i_flags
|= (p_sys
->i_top_field_first
) ? BLOCK_FLAG_TOP_FIELD_FIRST
515 : BLOCK_FLAG_BOTTOM_FIELD_FIRST
;
519 /* Special case for DVR-MS where we need to fully build pts from scratch
520 * and only use first dts as it does not monotonically increase
521 * This will NOT work with frame repeats and such, as we would need to fully
522 * fill the DPB to get accurate pts timings. */
523 if( unlikely( p_dec
->fmt_in
.i_original_fourcc
== VLC_FOURCC( 'D','V','R',' ') ) )
525 const bool b_first_xmited
= (p_sys
->i_prev_temporal_ref
!= p_sys
->i_temporal_ref
);
527 if( ( p_pic
->i_flags
& BLOCK_FLAG_TYPE_I
) && b_first_xmited
)
529 if( date_Get( &p_sys
->prev_iframe_dts
) == VLC_TS_INVALID
)
531 if( p_sys
->i_dts
!= VLC_TS_INVALID
)
533 date_Set( &p_sys
->dts
, p_sys
->i_dts
);
537 if( date_Get( &p_sys
->dts
) == VLC_TS_INVALID
)
539 date_Set( &p_sys
->dts
, VLC_TS_0
);
543 p_sys
->prev_iframe_dts
= p_sys
->dts
;
546 p_pic
->i_dts
= date_Get( &p_sys
->dts
);
548 /* Compute pts from poc */
549 date_t datepts
= p_sys
->prev_iframe_dts
;
550 date_Increment( &datepts
, (1 + p_sys
->i_temporal_ref
) * 2 );
552 /* Field picture second field case */
553 if( p_sys
->i_picture_structure
!= 0x03 )
555 /* first sent is not the first in display order */
556 if( (p_sys
->i_picture_structure
>> 1) != !p_sys
->i_top_field_first
&&
559 date_Increment( &datepts
, 2 );
563 p_pic
->i_pts
= date_Get( &datepts
);
565 if( date_Get( &p_sys
->dts
) != VLC_TS_INVALID
)
567 date_Increment( &p_sys
->dts
, i_num_fields
);
569 p_pic
->i_length
= date_Get( &p_sys
->dts
) - p_pic
->i_dts
;
571 p_sys
->i_prev_temporal_ref
= p_sys
->i_temporal_ref
;
573 else /* General case, use demuxer's dts/pts when set or interpolate */
575 if( p_sys
->b_low_delay
|| p_sys
->i_picture_type
== 0x03 )
577 /* Trivial case (DTS == PTS) */
578 /* Correct interpolated dts when we receive a new pts/dts */
579 if( p_sys
->i_pts
> VLC_TS_INVALID
)
580 date_Set( &p_sys
->dts
, p_sys
->i_pts
);
581 if( p_sys
->i_dts
> VLC_TS_INVALID
)
582 date_Set( &p_sys
->dts
, p_sys
->i_dts
);
586 /* Correct interpolated dts when we receive a new pts/dts */
587 if(p_sys
->i_last_ref_pts
> VLC_TS_INVALID
&& !p_sys
->b_second_field
)
588 date_Set( &p_sys
->dts
, p_sys
->i_last_ref_pts
);
589 if( p_sys
->i_dts
> VLC_TS_INVALID
)
590 date_Set( &p_sys
->dts
, p_sys
->i_dts
);
592 if( !p_sys
->b_second_field
)
593 p_sys
->i_last_ref_pts
= p_sys
->i_pts
;
596 p_pic
->i_dts
= date_Get( &p_sys
->dts
);
598 /* Set PTS only if we have a B frame or if it comes from the stream */
599 if( p_sys
->i_pts
> VLC_TS_INVALID
)
601 p_pic
->i_pts
= p_sys
->i_pts
;
603 else if( p_sys
->i_picture_type
== 0x03 )
605 p_pic
->i_pts
= p_pic
->i_dts
;
609 p_pic
->i_pts
= VLC_TS_INVALID
;
612 if( date_Get( &p_sys
->dts
) != VLC_TS_INVALID
)
614 date_Increment( &p_sys
->dts
, i_num_fields
);
616 p_pic
->i_length
= date_Get( &p_sys
->dts
) - p_pic
->i_dts
;
621 msg_Dbg( p_dec
, "pic: type=%d ref=%d nf=%d tff=%d dts=%"PRId64
" ptsdiff=%"PRId64
" len=%"PRId64
,
622 p_sys
->i_picture_structure
, p_sys
->i_temporal_ref
, i_num_fields
,
623 p_sys
->i_top_field_first
,
624 p_pic
->i_dts
, (p_pic
->i_pts
> VLC_TS_INVALID
) ? p_pic
->i_pts
- p_pic
->i_dts
: 0, p_pic
->i_length
);
629 p_sys
->p_frame
= NULL
;
630 p_sys
->pp_last
= &p_sys
->p_frame
;
631 p_sys
->b_frame_slice
= false;
633 if( p_sys
->i_picture_structure
!= 0x03 )
635 p_sys
->b_second_field
= !p_sys
->b_second_field
;
639 p_sys
->b_second_field
= 0;
643 p_sys
->b_cc_reset
= true;
644 p_sys
->i_cc_pts
= p_pic
->i_pts
;
645 p_sys
->i_cc_dts
= p_pic
->i_dts
;
646 p_sys
->i_cc_flags
= p_pic
->i_flags
& BLOCK_FLAG_TYPE_MASK
;
649 if( !p_pic
&& p_sys
->b_cc_reset
)
651 p_sys
->b_cc_reset
= false;
652 cc_Flush( &p_sys
->cc
);
658 * Check info of current fragment
660 if( startcode
== GROUP_STARTCODE
)
662 /* Group start code */
664 p_sys
->i_seq_old
> p_sys
->i_frame_rate
/p_sys
->i_frame_rate_base
)
666 /* Useful for mpeg1: repeat sequence header every second */
667 block_ChainLastAppend( &p_sys
->pp_last
, block_Duplicate( p_sys
->p_seq
) );
670 block_ChainLastAppend( &p_sys
->pp_last
, block_Duplicate( p_sys
->p_ext
) );
673 p_sys
->i_seq_old
= 0;
676 else if( startcode
== SEQUENCE_HEADER_STARTCODE
&& p_frag
->i_buffer
>= 8 )
678 /* Sequence header code */
679 static const int code_to_frame_rate
[16][2] =
681 { 1, 1 }, /* invalid */
682 { 24000, 1001 }, { 24, 1 }, { 25, 1 }, { 30000, 1001 },
683 { 30, 1 }, { 50, 1 }, { 60000, 1001 }, { 60, 1 },
684 /* Unofficial 15fps from Xing*/
686 /* Unofficial economy rates from libmpeg3 */
687 { 5000, 1001 }, { 1000, 1001 }, { 12000, 1001 }, { 15000, 1001 },
688 { 1, 1 }, { 1, 1 } /* invalid */
691 if( p_sys
->p_seq
) block_Release( p_sys
->p_seq
);
692 if( p_sys
->p_ext
) block_Release( p_sys
->p_ext
);
694 p_sys
->p_seq
= block_Duplicate( p_frag
);
695 p_sys
->i_seq_old
= 0;
698 p_dec
->fmt_out
.video
.i_visible_width
=
699 ( p_frag
->p_buffer
[4] << 4)|(p_frag
->p_buffer
[5] >> 4 );
700 p_dec
->fmt_out
.video
.i_width
= (p_dec
->fmt_out
.video
.i_visible_width
+ 0x0F) & ~0x0F;
701 p_dec
->fmt_out
.video
.i_visible_height
=
702 ( (p_frag
->p_buffer
[5]&0x0f) << 8 )|p_frag
->p_buffer
[6];
703 if( p_sys
->b_seq_progressive
)
704 p_dec
->fmt_out
.video
.i_height
= (p_dec
->fmt_out
.video
.i_visible_height
+ 0x0F) & ~0x0F;
706 p_dec
->fmt_out
.video
.i_height
= (p_dec
->fmt_out
.video
.i_visible_height
+ 0x1F) & ~0x1F;
707 p_sys
->i_aspect_ratio_info
= p_frag
->p_buffer
[7] >> 4;
709 /* TODO: MPEG1 aspect ratio */
711 p_sys
->i_frame_rate
= code_to_frame_rate
[p_frag
->p_buffer
[7]&0x0f][0];
712 p_sys
->i_frame_rate_base
=
713 code_to_frame_rate
[p_frag
->p_buffer
[7]&0x0f][1];
715 if( ( p_sys
->i_frame_rate
!= p_dec
->fmt_out
.video
.i_frame_rate
||
716 p_dec
->fmt_out
.video
.i_frame_rate_base
!= p_sys
->i_frame_rate_base
) &&
717 p_sys
->i_frame_rate
&& p_sys
->i_frame_rate_base
&& p_sys
->i_frame_rate
<= UINT_MAX
/2 )
719 date_Change( &p_sys
->dts
, 2 * p_sys
->i_frame_rate
, p_sys
->i_frame_rate_base
);
720 date_Change( &p_sys
->prev_iframe_dts
, 2 * p_sys
->i_frame_rate
, p_sys
->i_frame_rate_base
);
722 p_dec
->fmt_out
.video
.i_frame_rate
= p_sys
->i_frame_rate
;
723 p_dec
->fmt_out
.video
.i_frame_rate_base
= p_sys
->i_frame_rate_base
;
725 p_sys
->b_seq_progressive
= true;
726 p_sys
->b_low_delay
= true;
729 if ( !p_sys
->b_inited
)
731 msg_Dbg( p_dec
, "size %dx%d/%dx%d fps=%.3f",
732 p_dec
->fmt_out
.video
.i_visible_width
, p_dec
->fmt_out
.video
.i_visible_height
,
733 p_dec
->fmt_out
.video
.i_width
, p_dec
->fmt_out
.video
.i_height
,
734 p_sys
->i_frame_rate
/ (float)(p_sys
->i_frame_rate_base
? p_sys
->i_frame_rate_base
: 1) );
738 else if( startcode
== EXTENSION_STARTCODE
&& p_frag
->i_buffer
> 4 )
740 /* extension_start_code_identifier */
741 const enum extension_start_code_identifier_e extid
= p_frag
->p_buffer
[4] >> 4;
743 /* Extension start code */
744 if( extid
== SEQUENCE_EXTENSION_ID
)
747 static const int mpeg2_aspect
[16][2] =
749 {0,1}, {1,1}, {4,3}, {16,9}, {221,100},
750 {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1},
755 /* sequence extension */
756 if( p_sys
->p_ext
) block_Release( p_sys
->p_ext
);
757 p_sys
->p_ext
= block_Duplicate( p_frag
);
759 if( p_frag
->i_buffer
>= 10 )
761 p_sys
->b_seq_progressive
=
762 p_frag
->p_buffer
[5]&0x08 ? true : false;
764 p_frag
->p_buffer
[9]&0x80 ? true : false;
767 /* Do not set aspect ratio : in case we're transcoding,
768 * transcode will take our fmt_out as a fmt_in to libmpeg2.
769 * libmpeg2.c will then believe that the user has requested
770 * a specific aspect ratio, which she hasn't. Thus in case
771 * of aspect ratio change, we're screwed. --Meuuh
774 p_dec
->fmt_out
.video
.i_sar_num
=
775 mpeg2_aspect
[p_sys
->i_aspect_ratio_info
][0] *
776 p_dec
->fmt_out
.video
.i_height
;
777 p_dec
->fmt_out
.video
.i_sar_den
=
778 mpeg2_aspect
[p_sys
->i_aspect_ratio_info
][1] *
779 p_dec
->fmt_out
.video
.i_width
;
783 else if( extid
== PICTURE_CODING_EXTENSION_ID
&& p_frag
->i_buffer
> 8 )
785 /* picture extension */
786 p_sys
->i_picture_structure
= p_frag
->p_buffer
[6]&0x03;
787 p_sys
->i_top_field_first
= p_frag
->p_buffer
[7] >> 7;
788 p_sys
->i_repeat_first_field
= (p_frag
->p_buffer
[7]>>1)&0x01;
789 p_sys
->i_progressive_frame
= p_frag
->p_buffer
[8] >> 7;
791 else if( extid
== SEQUENCE_DISPLAY_EXTENSION_ID
&& p_frag
->i_buffer
> 8 )
793 /* Sequence display extension */
794 bool contains_color_description
= (p_frag
->p_buffer
[4] & 0x01);
795 //uint8_t video_format = (p_frag->p_buffer[4] & 0x0f) >> 1;
797 if( contains_color_description
&& p_frag
->i_buffer
> 11 )
799 uint8_t color_primaries
= p_frag
->p_buffer
[5];
800 uint8_t color_transfer
= p_frag
->p_buffer
[6];
801 uint8_t color_matrix
= p_frag
->p_buffer
[7];
802 switch( color_primaries
)
805 p_dec
->fmt_out
.video
.primaries
= COLOR_PRIMARIES_BT709
;
807 case 4: /* BT.470M */
808 case 5: /* BT.470BG */
809 p_dec
->fmt_out
.video
.primaries
= COLOR_PRIMARIES_BT601_625
;
811 case 6: /* SMPTE 170M */
812 case 7: /* SMPTE 240M */
813 p_dec
->fmt_out
.video
.primaries
= COLOR_PRIMARIES_BT601_525
;
818 switch( color_transfer
)
821 p_dec
->fmt_out
.video
.transfer
= TRANSFER_FUNC_BT709
;
823 case 4: /* BT.470M assumed gamma 2.2 */
824 p_dec
->fmt_out
.video
.transfer
= TRANSFER_FUNC_SRGB
;
826 case 5: /* BT.470BG */
827 case 6: /* SMPTE 170M */
828 p_dec
->fmt_out
.video
.transfer
= TRANSFER_FUNC_BT2020
;
831 p_dec
->fmt_out
.video
.transfer
= TRANSFER_FUNC_LINEAR
;
836 switch( color_matrix
)
839 p_dec
->fmt_out
.video
.space
= COLOR_SPACE_BT709
;
841 case 5: /* BT.470BG */
842 case 6: /* SMPTE 170 M */
843 case 7: /* SMPTE 240 M */
844 p_dec
->fmt_out
.video
.space
= COLOR_SPACE_BT601
;
853 else if( startcode
== USER_DATA_STARTCODE
&& p_frag
->i_buffer
> 8 )
855 /* Frame Packing extension identifier as H262 2012 Amd4 Annex L */
856 if( !memcmp( &p_frag
->p_buffer
[4], "JP3D", 4 ) &&
857 p_frag
->i_buffer
> 11 && p_frag
->p_buffer
[8] == 0x03 &&
858 p_dec
->fmt_in
.video
.multiview_mode
== MULTIVIEW_2D
)
860 video_multiview_mode_t mode
;
861 switch( p_frag
->p_buffer
[9] & 0x7F )
864 mode
= MULTIVIEW_STEREO_SBS
; break;
866 mode
= MULTIVIEW_STEREO_TB
; break;
869 mode
= MULTIVIEW_2D
; break;
871 p_dec
->fmt_out
.video
.multiview_mode
= mode
;
874 cc_ProbeAndExtract( &p_sys
->cc
, p_sys
->i_top_field_first
,
875 &p_frag
->p_buffer
[4], p_frag
->i_buffer
- 4 );
877 else if( startcode
== PICTURE_STARTCODE
)
879 /* Picture start code */
882 if( p_frag
->i_buffer
>= 6 )
884 p_sys
->i_temporal_ref
=
885 ( p_frag
->p_buffer
[4] << 2 )|(p_frag
->p_buffer
[5] >> 6);
886 p_sys
->i_picture_type
= ( p_frag
->p_buffer
[5] >> 3 ) & 0x03;
889 p_sys
->i_dts
= p_frag
->i_dts
;
890 p_sys
->i_pts
= p_frag
->i_pts
;
892 else if( startcode
>= SLICE_STARTCODE_FIRST
&&
893 startcode
<= SLICE_STARTCODE_LAST
)
895 /* Slice start code */
896 p_sys
->b_frame_slice
= true;
899 /* Append the block */
900 block_ChainLastAppend( &p_sys
->pp_last
, p_frag
);