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
, decoder_cc_desc_t
* );
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
, decoder_cc_desc_t
*p_desc
)
317 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
320 if( !p_sys
->cc
.b_reorder
&& p_sys
->cc
.i_data
<= 0 )
323 p_cc
= block_Alloc( p_sys
->cc
.i_data
);
326 memcpy( p_cc
->p_buffer
, p_sys
->cc
.p_data
, p_sys
->cc
.i_data
);
328 p_cc
->i_pts
= p_sys
->cc
.b_reorder
? p_sys
->i_cc_pts
: p_sys
->i_cc_dts
;
329 p_cc
->i_flags
= p_sys
->i_cc_flags
& BLOCK_FLAG_TYPE_MASK
;
331 p_desc
->i_608_channels
= p_sys
->cc
.i_608channels
;
332 p_desc
->i_708_channels
= p_sys
->cc
.i_708channels
;
333 p_desc
->i_reorder_depth
= p_sys
->cc
.b_reorder
? 0 : -1;
335 cc_Flush( &p_sys
->cc
);
339 /*****************************************************************************
341 *****************************************************************************/
342 static void PacketizeReset( void *p_private
, bool b_broken
)
344 VLC_UNUSED(b_broken
);
345 decoder_t
*p_dec
= p_private
;
346 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
348 p_sys
->i_next_block_flags
= BLOCK_FLAG_DISCONTINUITY
;
351 block_ChainRelease( p_sys
->p_frame
);
352 p_sys
->p_frame
= NULL
;
353 p_sys
->pp_last
= &p_sys
->p_frame
;
354 p_sys
->b_frame_slice
= false;
356 date_Set( &p_sys
->dts
, VLC_TS_INVALID
);
357 date_Set( &p_sys
->prev_iframe_dts
, VLC_TS_INVALID
);
360 p_sys
->i_last_ref_pts
= VLC_TS_INVALID
;
361 p_sys
->b_waiting_iframe
= p_sys
->b_sync_on_intra_frame
;
362 p_sys
->i_prev_temporal_ref
= 2048;
365 static block_t
*PacketizeParse( void *p_private
, bool *pb_ts_used
, block_t
*p_block
)
367 decoder_t
*p_dec
= p_private
;
368 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
370 /* Check if we have a picture start code */
371 *pb_ts_used
= p_block
->p_buffer
[3] == PICTURE_STARTCODE
;
373 p_block
= ParseMPEGBlock( p_dec
, p_block
);
376 p_block
->i_flags
|= p_sys
->i_next_block_flags
;
377 p_sys
->i_next_block_flags
= 0;
383 static int PacketizeValidate( void *p_private
, block_t
*p_au
)
385 decoder_t
*p_dec
= p_private
;
386 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
388 if( unlikely( p_sys
->b_waiting_iframe
) )
390 if( (p_au
->i_flags
& BLOCK_FLAG_TYPE_I
) == 0 )
392 msg_Dbg( p_dec
, "waiting on intra frame" );
395 msg_Dbg( p_dec
, "synced on intra frame" );
396 p_sys
->b_waiting_iframe
= false;
399 /* We've just started the stream, wait for the first PTS.
400 * We discard here so we can still get the sequence header. */
401 if( unlikely( p_sys
->i_dts
<= VLC_TS_INVALID
&& p_sys
->i_pts
<= VLC_TS_INVALID
&&
402 date_Get( &p_sys
->dts
) <= VLC_TS_INVALID
))
404 msg_Dbg( p_dec
, "need a starting pts/dts" );
408 /* When starting the stream we can have the first frame with
409 * an invalid DTS (i_interpolated_pts is initialized to VLC_TS_INVALID) */
410 if( unlikely( p_au
->i_dts
<= VLC_TS_INVALID
) )
411 p_au
->i_dts
= p_au
->i_pts
;
415 /*****************************************************************************
416 * ParseMPEGBlock: Re-assemble fragments into a block containing a picture
417 *****************************************************************************/
418 static block_t
*ParseMPEGBlock( decoder_t
*p_dec
, block_t
*p_frag
)
420 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
421 block_t
*p_pic
= NULL
;
423 const enum mpeg_startcode_e startcode
= p_frag
->p_buffer
[3];
425 * Check if previous picture is finished
427 if( ( p_sys
->b_frame_slice
&&
428 (startcode
== PICTURE_STARTCODE
|| startcode
> SLICE_STARTCODE_LAST
) ) &&
429 p_sys
->p_seq
== NULL
)
431 /* We have a picture but without a sequence header we can't
433 msg_Dbg( p_dec
, "waiting for sequence start" );
434 if( p_sys
->p_frame
) block_ChainRelease( p_sys
->p_frame
);
435 p_sys
->p_frame
= NULL
;
436 p_sys
->pp_last
= &p_sys
->p_frame
;
437 p_sys
->b_frame_slice
= false;
440 else if( p_sys
->b_frame_slice
&&
441 (startcode
== PICTURE_STARTCODE
||
442 (startcode
> SLICE_STARTCODE_LAST
&& startcode
!= EXTENSION_STARTCODE
)) )
444 const bool b_eos
= startcode
== SEQUENCE_END_STARTCODE
;
448 block_ChainLastAppend( &p_sys
->pp_last
, p_frag
);
452 p_pic
= block_ChainGather( p_sys
->p_frame
);
457 p_pic
->i_flags
|= BLOCK_FLAG_END_OF_SEQUENCE
;
459 unsigned i_num_fields
;
461 if( !p_sys
->b_seq_progressive
&& p_sys
->i_picture_structure
!= 0x03 /* Field Picture */ )
466 if( p_sys
->b_seq_progressive
)
468 if( p_sys
->i_top_field_first
== 0 &&
469 p_sys
->i_repeat_first_field
== 1 )
473 else if( p_sys
->i_top_field_first
== 1 &&
474 p_sys
->i_repeat_first_field
== 1 )
481 if( p_sys
->i_picture_structure
== 0x03 /* Frame Picture */ )
483 if( p_sys
->i_progressive_frame
&& p_sys
->i_repeat_first_field
)
490 switch ( p_sys
->i_picture_type
)
493 p_pic
->i_flags
|= BLOCK_FLAG_TYPE_I
;
496 p_pic
->i_flags
|= BLOCK_FLAG_TYPE_P
;
499 p_pic
->i_flags
|= BLOCK_FLAG_TYPE_B
;
503 if( !p_sys
->b_seq_progressive
)
505 if( p_sys
->i_picture_structure
< 0x03 )
507 p_pic
->i_flags
|= BLOCK_FLAG_SINGLE_FIELD
;
508 p_pic
->i_flags
|= (p_sys
->i_picture_structure
== 0x01) ? BLOCK_FLAG_TOP_FIELD_FIRST
509 : BLOCK_FLAG_BOTTOM_FIELD_FIRST
;
511 else /* if( p_sys->i_picture_structure == 0x03 ) */
513 p_pic
->i_flags
|= (p_sys
->i_top_field_first
) ? BLOCK_FLAG_TOP_FIELD_FIRST
514 : BLOCK_FLAG_BOTTOM_FIELD_FIRST
;
518 /* Special case for DVR-MS where we need to fully build pts from scratch
519 * and only use first dts as it does not monotonically increase
520 * This will NOT work with frame repeats and such, as we would need to fully
521 * fill the DPB to get accurate pts timings. */
522 if( unlikely( p_dec
->fmt_in
.i_original_fourcc
== VLC_FOURCC( 'D','V','R',' ') ) )
524 const bool b_first_xmited
= (p_sys
->i_prev_temporal_ref
!= p_sys
->i_temporal_ref
);
526 if( ( p_pic
->i_flags
& BLOCK_FLAG_TYPE_I
) && b_first_xmited
)
528 if( date_Get( &p_sys
->prev_iframe_dts
) == VLC_TS_INVALID
)
530 if( p_sys
->i_dts
!= VLC_TS_INVALID
)
532 date_Set( &p_sys
->dts
, p_sys
->i_dts
);
536 if( date_Get( &p_sys
->dts
) == VLC_TS_INVALID
)
538 date_Set( &p_sys
->dts
, VLC_TS_0
);
542 p_sys
->prev_iframe_dts
= p_sys
->dts
;
545 p_pic
->i_dts
= date_Get( &p_sys
->dts
);
547 /* Compute pts from poc */
548 date_t datepts
= p_sys
->prev_iframe_dts
;
549 date_Increment( &datepts
, (1 + p_sys
->i_temporal_ref
) * 2 );
551 /* Field picture second field case */
552 if( p_sys
->i_picture_structure
!= 0x03 )
554 /* first sent is not the first in display order */
555 if( (p_sys
->i_picture_structure
>> 1) != !p_sys
->i_top_field_first
&&
558 date_Increment( &datepts
, 2 );
562 p_pic
->i_pts
= date_Get( &datepts
);
564 if( date_Get( &p_sys
->dts
) != VLC_TS_INVALID
)
566 date_Increment( &p_sys
->dts
, i_num_fields
);
568 p_pic
->i_length
= date_Get( &p_sys
->dts
) - p_pic
->i_dts
;
570 p_sys
->i_prev_temporal_ref
= p_sys
->i_temporal_ref
;
572 else /* General case, use demuxer's dts/pts when set or interpolate */
574 if( p_sys
->b_low_delay
|| p_sys
->i_picture_type
== 0x03 )
576 /* Trivial case (DTS == PTS) */
577 /* Correct interpolated dts when we receive a new pts/dts */
578 if( p_sys
->i_pts
> VLC_TS_INVALID
)
579 date_Set( &p_sys
->dts
, p_sys
->i_pts
);
580 if( p_sys
->i_dts
> VLC_TS_INVALID
)
581 date_Set( &p_sys
->dts
, p_sys
->i_dts
);
585 /* Correct interpolated dts when we receive a new pts/dts */
586 if(p_sys
->i_last_ref_pts
> VLC_TS_INVALID
&& !p_sys
->b_second_field
)
587 date_Set( &p_sys
->dts
, p_sys
->i_last_ref_pts
);
588 if( p_sys
->i_dts
> VLC_TS_INVALID
)
589 date_Set( &p_sys
->dts
, p_sys
->i_dts
);
591 if( !p_sys
->b_second_field
)
592 p_sys
->i_last_ref_pts
= p_sys
->i_pts
;
595 p_pic
->i_dts
= date_Get( &p_sys
->dts
);
597 /* Set PTS only if we have a B frame or if it comes from the stream */
598 if( p_sys
->i_pts
> VLC_TS_INVALID
)
600 p_pic
->i_pts
= p_sys
->i_pts
;
602 else if( p_sys
->i_picture_type
== 0x03 )
604 p_pic
->i_pts
= p_pic
->i_dts
;
608 p_pic
->i_pts
= VLC_TS_INVALID
;
611 if( date_Get( &p_sys
->dts
) != VLC_TS_INVALID
)
613 date_Increment( &p_sys
->dts
, i_num_fields
);
615 p_pic
->i_length
= date_Get( &p_sys
->dts
) - p_pic
->i_dts
;
620 msg_Dbg( p_dec
, "pic: type=%d ref=%d nf=%d tff=%d dts=%"PRId64
" ptsdiff=%"PRId64
" len=%"PRId64
,
621 p_sys
->i_picture_structure
, p_sys
->i_temporal_ref
, i_num_fields
,
622 p_sys
->i_top_field_first
,
623 p_pic
->i_dts
, (p_pic
->i_pts
> VLC_TS_INVALID
) ? p_pic
->i_pts
- p_pic
->i_dts
: 0, p_pic
->i_length
);
628 p_sys
->p_frame
= NULL
;
629 p_sys
->pp_last
= &p_sys
->p_frame
;
630 p_sys
->b_frame_slice
= false;
632 if( p_sys
->i_picture_structure
!= 0x03 )
634 p_sys
->b_second_field
= !p_sys
->b_second_field
;
638 p_sys
->b_second_field
= 0;
642 p_sys
->b_cc_reset
= true;
643 p_sys
->i_cc_pts
= p_pic
->i_pts
;
644 p_sys
->i_cc_dts
= p_pic
->i_dts
;
645 p_sys
->i_cc_flags
= p_pic
->i_flags
& BLOCK_FLAG_TYPE_MASK
;
648 if( !p_pic
&& p_sys
->b_cc_reset
)
650 p_sys
->b_cc_reset
= false;
651 cc_Flush( &p_sys
->cc
);
657 * Check info of current fragment
659 if( startcode
== GROUP_STARTCODE
)
661 /* Group start code */
663 p_sys
->i_seq_old
> p_sys
->i_frame_rate
/p_sys
->i_frame_rate_base
)
665 /* Useful for mpeg1: repeat sequence header every second */
666 block_ChainLastAppend( &p_sys
->pp_last
, block_Duplicate( p_sys
->p_seq
) );
669 block_ChainLastAppend( &p_sys
->pp_last
, block_Duplicate( p_sys
->p_ext
) );
672 p_sys
->i_seq_old
= 0;
675 else if( startcode
== SEQUENCE_HEADER_STARTCODE
&& p_frag
->i_buffer
>= 8 )
677 /* Sequence header code */
678 static const int code_to_frame_rate
[16][2] =
680 { 1, 1 }, /* invalid */
681 { 24000, 1001 }, { 24, 1 }, { 25, 1 }, { 30000, 1001 },
682 { 30, 1 }, { 50, 1 }, { 60000, 1001 }, { 60, 1 },
683 /* Unofficial 15fps from Xing*/
685 /* Unofficial economy rates from libmpeg3 */
686 { 5000, 1001 }, { 1000, 1001 }, { 12000, 1001 }, { 15000, 1001 },
687 { 1, 1 }, { 1, 1 } /* invalid */
690 if( p_sys
->p_seq
) block_Release( p_sys
->p_seq
);
691 if( p_sys
->p_ext
) block_Release( p_sys
->p_ext
);
693 p_sys
->p_seq
= block_Duplicate( p_frag
);
694 p_sys
->i_seq_old
= 0;
697 p_dec
->fmt_out
.video
.i_visible_width
=
698 ( p_frag
->p_buffer
[4] << 4)|(p_frag
->p_buffer
[5] >> 4 );
699 p_dec
->fmt_out
.video
.i_width
= (p_dec
->fmt_out
.video
.i_visible_width
+ 0x0F) & ~0x0F;
700 p_dec
->fmt_out
.video
.i_visible_height
=
701 ( (p_frag
->p_buffer
[5]&0x0f) << 8 )|p_frag
->p_buffer
[6];
702 if( p_sys
->b_seq_progressive
)
703 p_dec
->fmt_out
.video
.i_height
= (p_dec
->fmt_out
.video
.i_visible_height
+ 0x0F) & ~0x0F;
705 p_dec
->fmt_out
.video
.i_height
= (p_dec
->fmt_out
.video
.i_visible_height
+ 0x1F) & ~0x1F;
706 p_sys
->i_aspect_ratio_info
= p_frag
->p_buffer
[7] >> 4;
708 /* TODO: MPEG1 aspect ratio */
710 p_sys
->i_frame_rate
= code_to_frame_rate
[p_frag
->p_buffer
[7]&0x0f][0];
711 p_sys
->i_frame_rate_base
=
712 code_to_frame_rate
[p_frag
->p_buffer
[7]&0x0f][1];
714 if( ( p_sys
->i_frame_rate
!= p_dec
->fmt_out
.video
.i_frame_rate
||
715 p_dec
->fmt_out
.video
.i_frame_rate_base
!= p_sys
->i_frame_rate_base
) &&
716 p_sys
->i_frame_rate
&& p_sys
->i_frame_rate_base
&& p_sys
->i_frame_rate
<= UINT_MAX
/2 )
718 date_Change( &p_sys
->dts
, 2 * p_sys
->i_frame_rate
, p_sys
->i_frame_rate_base
);
719 date_Change( &p_sys
->prev_iframe_dts
, 2 * p_sys
->i_frame_rate
, p_sys
->i_frame_rate_base
);
721 p_dec
->fmt_out
.video
.i_frame_rate
= p_sys
->i_frame_rate
;
722 p_dec
->fmt_out
.video
.i_frame_rate_base
= p_sys
->i_frame_rate_base
;
724 p_sys
->b_seq_progressive
= true;
725 p_sys
->b_low_delay
= true;
728 if ( !p_sys
->b_inited
)
730 msg_Dbg( p_dec
, "size %dx%d/%dx%d fps=%.3f",
731 p_dec
->fmt_out
.video
.i_visible_width
, p_dec
->fmt_out
.video
.i_visible_height
,
732 p_dec
->fmt_out
.video
.i_width
, p_dec
->fmt_out
.video
.i_height
,
733 p_sys
->i_frame_rate
/ (float)(p_sys
->i_frame_rate_base
? p_sys
->i_frame_rate_base
: 1) );
737 else if( startcode
== EXTENSION_STARTCODE
&& p_frag
->i_buffer
> 4 )
739 /* extension_start_code_identifier */
740 const enum extension_start_code_identifier_e extid
= p_frag
->p_buffer
[4] >> 4;
742 /* Extension start code */
743 if( extid
== SEQUENCE_EXTENSION_ID
)
746 static const int mpeg2_aspect
[16][2] =
748 {0,1}, {1,1}, {4,3}, {16,9}, {221,100},
749 {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1},
754 /* sequence extension */
755 if( p_sys
->p_ext
) block_Release( p_sys
->p_ext
);
756 p_sys
->p_ext
= block_Duplicate( p_frag
);
758 if( p_frag
->i_buffer
>= 10 )
760 p_sys
->b_seq_progressive
=
761 p_frag
->p_buffer
[5]&0x08 ? true : false;
763 p_frag
->p_buffer
[9]&0x80 ? true : false;
766 /* Do not set aspect ratio : in case we're transcoding,
767 * transcode will take our fmt_out as a fmt_in to libmpeg2.
768 * libmpeg2.c will then believe that the user has requested
769 * a specific aspect ratio, which she hasn't. Thus in case
770 * of aspect ratio change, we're screwed. --Meuuh
773 p_dec
->fmt_out
.video
.i_sar_num
=
774 mpeg2_aspect
[p_sys
->i_aspect_ratio_info
][0] *
775 p_dec
->fmt_out
.video
.i_height
;
776 p_dec
->fmt_out
.video
.i_sar_den
=
777 mpeg2_aspect
[p_sys
->i_aspect_ratio_info
][1] *
778 p_dec
->fmt_out
.video
.i_width
;
782 else if( extid
== PICTURE_CODING_EXTENSION_ID
&& p_frag
->i_buffer
> 8 )
784 /* picture extension */
785 p_sys
->i_picture_structure
= p_frag
->p_buffer
[6]&0x03;
786 p_sys
->i_top_field_first
= p_frag
->p_buffer
[7] >> 7;
787 p_sys
->i_repeat_first_field
= (p_frag
->p_buffer
[7]>>1)&0x01;
788 p_sys
->i_progressive_frame
= p_frag
->p_buffer
[8] >> 7;
790 else if( extid
== SEQUENCE_DISPLAY_EXTENSION_ID
&& p_frag
->i_buffer
> 8 )
792 /* Sequence display extension */
793 bool contains_color_description
= (p_frag
->p_buffer
[4] & 0x01);
794 //uint8_t video_format = (p_frag->p_buffer[4] & 0x0f) >> 1;
796 if( contains_color_description
&& p_frag
->i_buffer
> 11 )
798 uint8_t color_primaries
= p_frag
->p_buffer
[5];
799 uint8_t color_transfer
= p_frag
->p_buffer
[6];
800 uint8_t color_matrix
= p_frag
->p_buffer
[7];
801 switch( color_primaries
)
804 p_dec
->fmt_out
.video
.primaries
= COLOR_PRIMARIES_BT709
;
806 case 4: /* BT.470M */
807 case 5: /* BT.470BG */
808 p_dec
->fmt_out
.video
.primaries
= COLOR_PRIMARIES_BT601_625
;
810 case 6: /* SMPTE 170M */
811 case 7: /* SMPTE 240M */
812 p_dec
->fmt_out
.video
.primaries
= COLOR_PRIMARIES_BT601_525
;
817 switch( color_transfer
)
820 p_dec
->fmt_out
.video
.transfer
= TRANSFER_FUNC_BT709
;
822 case 4: /* BT.470M assumed gamma 2.2 */
823 p_dec
->fmt_out
.video
.transfer
= TRANSFER_FUNC_SRGB
;
825 case 5: /* BT.470BG */
826 case 6: /* SMPTE 170M */
827 p_dec
->fmt_out
.video
.transfer
= TRANSFER_FUNC_BT2020
;
830 p_dec
->fmt_out
.video
.transfer
= TRANSFER_FUNC_LINEAR
;
835 switch( color_matrix
)
838 p_dec
->fmt_out
.video
.space
= COLOR_SPACE_BT709
;
840 case 5: /* BT.470BG */
841 case 6: /* SMPTE 170 M */
842 case 7: /* SMPTE 240 M */
843 p_dec
->fmt_out
.video
.space
= COLOR_SPACE_BT601
;
852 else if( startcode
== USER_DATA_STARTCODE
&& p_frag
->i_buffer
> 8 )
854 /* Frame Packing extension identifier as H262 2012 Amd4 Annex L */
855 if( !memcmp( &p_frag
->p_buffer
[4], "JP3D", 4 ) &&
856 p_frag
->i_buffer
> 11 && p_frag
->p_buffer
[8] == 0x03 &&
857 p_dec
->fmt_in
.video
.multiview_mode
== MULTIVIEW_2D
)
859 video_multiview_mode_t mode
;
860 switch( p_frag
->p_buffer
[9] & 0x7F )
863 mode
= MULTIVIEW_STEREO_SBS
; break;
865 mode
= MULTIVIEW_STEREO_TB
; break;
868 mode
= MULTIVIEW_2D
; break;
870 p_dec
->fmt_out
.video
.multiview_mode
= mode
;
873 cc_ProbeAndExtract( &p_sys
->cc
, p_sys
->i_top_field_first
,
874 &p_frag
->p_buffer
[4], p_frag
->i_buffer
- 4 );
876 else if( startcode
== PICTURE_STARTCODE
)
878 /* Picture start code */
881 if( p_frag
->i_buffer
>= 6 )
883 p_sys
->i_temporal_ref
=
884 ( p_frag
->p_buffer
[4] << 2 )|(p_frag
->p_buffer
[5] >> 6);
885 p_sys
->i_picture_type
= ( p_frag
->p_buffer
[5] >> 3 ) & 0x03;
888 p_sys
->i_dts
= p_frag
->i_dts
;
889 p_sys
->i_pts
= p_frag
->i_pts
;
891 else if( startcode
>= SLICE_STARTCODE_FIRST
&&
892 startcode
<= SLICE_STARTCODE_LAST
)
894 /* Slice start code */
895 p_sys
->b_frame_slice
= true;
898 /* Append the block */
899 block_ChainLastAppend( &p_sys
->pp_last
, p_frag
);