1 /*****************************************************************************
2 * mpeg4video.c: mpeg 4 video packetizer
3 *****************************************************************************
4 * Copyright (C) 2001-2006 VLC authors and VideoLAN
7 * Authors: Gildas Bazin <gbazin@videolan.org>
8 * Laurent Aimar <fenrir@via.ecp.fr>
9 * Eric Petit <titer@videolan.org>
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
37 #include <vlc_codec.h>
38 #include <vlc_block.h>
41 #include <vlc_block_helper.h>
42 #include "packetizer_helper.h"
43 #include "startcode_helper.h"
44 #include "hxxx_nal.h" /* colour values/mappings */
46 /*****************************************************************************
48 *****************************************************************************/
49 static int Open ( vlc_object_t
* );
50 static void Close( vlc_object_t
* );
53 set_category( CAT_SOUT
)
54 set_subcategory( SUBCAT_SOUT_PACKETIZER
)
55 set_description( N_("MPEG4 video packetizer") )
56 set_capability( "packetizer", 50 )
57 set_callbacks( Open
, Close
)
60 /****************************************************************************
62 ****************************************************************************/
68 packetizer_t packetizer
;
73 mtime_t i_interpolated_pts
;
74 mtime_t i_interpolated_dts
;
75 mtime_t i_last_ref_pts
;
76 mtime_t i_last_time_ref
;
79 mtime_t i_last_timeincr
;
90 /* Current frame being built */
95 static block_t
*Packetize( decoder_t
*, block_t
** );
96 static void PacketizeFlush( decoder_t
* );
98 static void PacketizeReset( void *p_private
, bool b_broken
);
99 static block_t
*PacketizeParse( void *p_private
, bool *pb_ts_used
, block_t
* );
100 static int PacketizeValidate( void *p_private
, block_t
* );
102 static block_t
*ParseMPEGBlock( decoder_t
*, block_t
* );
103 static int ParseVOL( decoder_t
*, es_format_t
*, uint8_t *, int );
104 static int ParseVO( decoder_t
*, block_t
* );
105 static int ParseVOP( decoder_t
*, block_t
* );
106 static int vlc_log2( unsigned int );
108 #define VIDEO_OBJECT_MASK 0x01f
109 #define VIDEO_OBJECT_LAYER_MASK 0x00f
111 #define VIDEO_OBJECT_START_CODE 0x100
112 #define VIDEO_OBJECT_LAYER_START_CODE 0x120
113 #define RESERVED_START_CODE 0x130
114 #define VISUAL_OBJECT_SEQUENCE_START_CODE 0x1b0
115 #define VISUAL_OBJECT_SEQUENCE_END_CODE 0x1b1
116 #define USER_DATA_START_CODE 0x1b2
117 #define GROUP_OF_VOP_START_CODE 0x1b3
118 #define VIDEO_SESSION_ERROR_CODE 0x1b4
119 #define VISUAL_OBJECT_START_CODE 0x1b5
120 #define VOP_START_CODE 0x1b6
121 #define FACE_OBJECT_START_CODE 0x1ba
122 #define FACE_OBJECT_PLANE_START_CODE 0x1bb
123 #define MESH_OBJECT_START_CODE 0x1bc
124 #define MESH_OBJECT_PLANE_START_CODE 0x1bd
125 #define STILL_TEXTURE_OBJECT_START_CODE 0x1be
126 #define TEXTURE_SPATIAL_LAYER_START_CODE 0x1bf
127 #define TEXTURE_SNR_LAYER_START_CODE 0x1c0
129 static const uint8_t p_mp4v_startcode
[3] = { 0x00, 0x00, 0x01 };
131 /*****************************************************************************
132 * Open: probe the packetizer and return score
133 *****************************************************************************/
134 static int Open( vlc_object_t
*p_this
)
136 decoder_t
*p_dec
= (decoder_t
*)p_this
;
137 decoder_sys_t
*p_sys
;
139 if( p_dec
->fmt_in
.i_codec
!= VLC_CODEC_MP4V
)
142 /* Allocate the memory needed to store the decoder's structure */
143 if( ( p_dec
->p_sys
= p_sys
= malloc( sizeof(decoder_sys_t
) ) ) == NULL
)
145 memset( p_sys
, 0, sizeof(decoder_sys_t
) );
148 packetizer_Init( &p_sys
->packetizer
,
149 p_mp4v_startcode
, sizeof(p_mp4v_startcode
), startcode_FindAnnexB
,
151 PacketizeReset
, PacketizeParse
, PacketizeValidate
, p_dec
);
153 p_sys
->p_frame
= NULL
;
154 p_sys
->pp_last
= &p_sys
->p_frame
;
156 /* Setup properties */
157 es_format_Copy( &p_dec
->fmt_out
, &p_dec
->fmt_in
);
158 p_dec
->fmt_out
.i_codec
= VLC_CODEC_MP4V
;
160 if( p_dec
->fmt_out
.i_extra
)
163 msg_Dbg( p_dec
, "opening with vol size: %d", p_dec
->fmt_out
.i_extra
);
164 ParseVOL( p_dec
, &p_dec
->fmt_out
,
165 p_dec
->fmt_out
.p_extra
, p_dec
->fmt_out
.i_extra
);
169 p_dec
->pf_packetize
= Packetize
;
170 p_dec
->pf_flush
= PacketizeFlush
;
175 /*****************************************************************************
176 * Close: clean up the packetizer
177 *****************************************************************************/
178 static void Close( vlc_object_t
*p_this
)
180 decoder_t
*p_dec
= (decoder_t
*)p_this
;
181 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
183 packetizer_Clean( &p_sys
->packetizer
);
185 block_ChainRelease( p_sys
->p_frame
);
189 /****************************************************************************
190 * Packetize: the whole thing
191 ****************************************************************************/
192 static block_t
*Packetize( decoder_t
*p_dec
, block_t
**pp_block
)
194 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
196 return packetizer_Packetize( &p_sys
->packetizer
, pp_block
);
199 static void PacketizeFlush( decoder_t
*p_dec
)
201 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
203 packetizer_Flush( &p_sys
->packetizer
);
206 /*****************************************************************************
208 *****************************************************************************/
209 static void PacketizeReset( void *p_private
, bool b_broken
)
211 decoder_t
*p_dec
= p_private
;
212 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
217 block_ChainRelease( p_sys
->p_frame
);
218 p_sys
->p_frame
= NULL
;
219 p_sys
->pp_last
= &p_sys
->p_frame
;
222 p_sys
->i_interpolated_pts
=
223 p_sys
->i_interpolated_dts
=
224 p_sys
->i_last_ref_pts
= VLC_TS_INVALID
;
226 p_sys
->i_last_time_ref
=
229 p_sys
->i_last_timeincr
= 0;
232 static block_t
*PacketizeParse( void *p_private
, bool *pb_ts_used
, block_t
*p_block
)
234 decoder_t
*p_dec
= p_private
;
235 const mtime_t i_dts
= p_block
->i_dts
;
236 const mtime_t i_pts
= p_block
->i_pts
;
238 block_t
*p_au
= ParseMPEGBlock( p_dec
, p_block
);
240 *pb_ts_used
= p_au
&& p_au
->i_dts
== i_dts
&& p_au
->i_pts
== i_pts
;
246 static int PacketizeValidate( void *p_private
, block_t
*p_au
)
248 decoder_t
*p_dec
= p_private
;
249 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
251 /* We've just started the stream, wait for the first PTS.
252 * We discard here so we can still get the sequence header. */
253 if( p_sys
->i_interpolated_pts
== VLC_TS_INVALID
&&
254 p_sys
->i_interpolated_dts
== VLC_TS_INVALID
)
256 msg_Dbg( p_dec
, "need a starting pts/dts" );
260 /* When starting the stream we can have the first frame with
261 * a null DTS (i_interpolated_pts is initialized to 0) */
263 p_au
->i_dts
= p_au
->i_pts
;
267 /*****************************************************************************
268 * ParseMPEGBlock: Re-assemble fragments into a block containing a picture
269 *****************************************************************************/
270 static block_t
*ParseMPEGBlock( decoder_t
*p_dec
, block_t
*p_frag
)
272 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
273 block_t
*p_pic
= NULL
;
275 if( p_frag
->i_buffer
< 4 )
278 const uint32_t i_startcode
= GetDWBE( p_frag
->p_buffer
);
279 if( i_startcode
== VISUAL_OBJECT_SEQUENCE_START_CODE
||
280 i_startcode
== VISUAL_OBJECT_SEQUENCE_END_CODE
||
281 i_startcode
== USER_DATA_START_CODE
)
282 { /* VOS and USERDATA */
284 /* Remove VOS start/end code from the original stream */
285 block_Release( p_frag
);
287 /* Append the block for now since ts/ps muxers rely on VOL
288 * being present in the stream */
289 block_ChainLastAppend( &p_sys
->pp_last
, p_frag
);
293 else if( i_startcode
>= VIDEO_OBJECT_LAYER_START_CODE
&&
294 i_startcode
< RESERVED_START_CODE
)
296 /* Copy the complete VOL */
297 if( (size_t)p_dec
->fmt_out
.i_extra
!= p_frag
->i_buffer
)
299 p_dec
->fmt_out
.p_extra
=
300 xrealloc( p_dec
->fmt_out
.p_extra
, p_frag
->i_buffer
);
301 p_dec
->fmt_out
.i_extra
= p_frag
->i_buffer
;
303 memcpy( p_dec
->fmt_out
.p_extra
, p_frag
->p_buffer
, p_frag
->i_buffer
);
304 ParseVOL( p_dec
, &p_dec
->fmt_out
,
305 p_dec
->fmt_out
.p_extra
, p_dec
->fmt_out
.i_extra
);
308 /* Remove from the original stream */
309 block_Release( p_frag
);
311 /* Append the block for now since ts/ps muxers rely on VOL
312 * being present in the stream */
313 block_ChainLastAppend( &p_sys
->pp_last
, p_frag
);
319 if( !p_dec
->fmt_out
.i_extra
)
321 msg_Warn( p_dec
, "waiting for VOL" );
322 block_Release( p_frag
);
326 /* Append the block */
327 block_ChainLastAppend( &p_sys
->pp_last
, p_frag
);
330 if( i_startcode
== VISUAL_OBJECT_START_CODE
)
332 ParseVO( p_dec
, p_frag
);
335 if( i_startcode
== VOP_START_CODE
&&
336 ParseVOP( p_dec
, p_frag
) == VLC_SUCCESS
)
338 /* We are dealing with a VOP */
339 p_pic
= block_ChainGather( p_sys
->p_frame
);
340 p_pic
->i_flags
= p_sys
->i_flags
;
341 p_pic
->i_pts
= p_sys
->i_interpolated_pts
;
342 p_pic
->i_dts
= p_sys
->i_interpolated_dts
;
345 p_sys
->p_frame
= NULL
;
346 p_sys
->pp_last
= &p_sys
->p_frame
;
354 * - support aspect ratio
356 static int ParseVOL( decoder_t
*p_dec
, es_format_t
*fmt
,
357 uint8_t *p_vol
, int i_vol
)
359 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
360 int i_vo_ver_id
, i_ar
, i_shape
;
368 if( p_vol
[0] == 0x00 && p_vol
[1] == 0x00 && p_vol
[2] == 0x01 &&
369 p_vol
[3] >= 0x20 && p_vol
[3] <= 0x2f ) break;
374 bs_init( &s
, &p_vol
[4], i_vol
- 4 );
376 bs_skip( &s
, 1 ); /* random access */
377 bs_skip( &s
, 8 ); /* vo_type */
380 i_vo_ver_id
= bs_read( &s
, 4 );
387 i_ar
= bs_read( &s
, 4 );
390 bs_skip( &s
, 8 ); /* ar_width */
391 bs_skip( &s
, 8 ); /* ar_height */
395 /* vol control parameter */
396 bs_skip( &s
, 2 ); /* chroma_format */
397 bs_read1( &s
); /* low_delay */
410 /* shape 0->RECT, 1->BIN, 2->BIN_ONLY, 3->GRAY */
411 i_shape
= bs_read( &s
, 2 );
412 if( i_shape
== 3 && i_vo_ver_id
!= 1 )
417 if( !bs_read1( &s
) ) return VLC_EGENERIC
; /* Marker */
419 p_sys
->i_fps_num
= bs_read( &s
, 16 ); /* Time increment resolution*/
420 if( !p_sys
->i_fps_num
) p_sys
->i_fps_num
= 1;
422 if( !bs_read1( &s
) ) return VLC_EGENERIC
; /* Marker */
426 int i_time_increment_bits
= vlc_log2( p_sys
->i_fps_num
- 1 ) + 1;
428 if( i_time_increment_bits
< 1 ) i_time_increment_bits
= 1;
430 p_sys
->i_fps_den
= bs_read( &s
, i_time_increment_bits
);
435 fmt
->video
.i_width
= bs_read( &s
, 13 );
437 fmt
->video
.i_height
= bs_read( &s
, 13 );
444 static int ParseVO( decoder_t
*p_dec
, block_t
*p_vo
)
447 bs_init( &s
, &p_vo
->p_buffer
[4], p_vo
->i_buffer
- 4 );
451 const uint8_t visual_object_type
= bs_read( &s
, 4 );
452 if( visual_object_type
== 1 /* video ID */ ||
453 visual_object_type
== 2 /* still texture ID */ )
455 uint8_t colour_primaries
= 1;
456 uint8_t colour_xfer
= 1;
457 uint8_t colour_matrix_coeff
= 1;
458 uint8_t full_range
= 0;
459 if( bs_read1( &s
) ) /* video_signal_type */
462 full_range
= bs_read( &s
, 1 );
463 if( bs_read( &s
, 1 ) ) /* colour description */
465 colour_primaries
= bs_read( &s
, 8 );
466 colour_xfer
= bs_read( &s
, 8 );
467 colour_matrix_coeff
= bs_read( &s
, 8 );
471 if( p_dec
->fmt_in
.video
.primaries
== COLOR_PRIMARIES_UNDEF
)
473 p_dec
->fmt_out
.video
.primaries
= hxxx_colour_primaries_to_vlc( colour_primaries
);
474 p_dec
->fmt_out
.video
.transfer
= hxxx_transfer_characteristics_to_vlc( colour_xfer
);
475 p_dec
->fmt_out
.video
.space
= hxxx_matrix_coeffs_to_vlc( colour_matrix_coeff
);
476 p_dec
->fmt_out
.video
.b_color_range_full
= full_range
;
483 static int ParseVOP( decoder_t
*p_dec
, block_t
*p_vop
)
485 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
486 int64_t i_time_increment
, i_time_ref
;
487 int i_modulo_time_base
= 0, i_time_increment_bits
;
490 bs_init( &s
, &p_vop
->p_buffer
[4], p_vop
->i_buffer
- 4 );
492 switch( bs_read( &s
, 2 ) )
495 p_sys
->i_flags
= BLOCK_FLAG_TYPE_I
;
498 p_sys
->i_flags
= BLOCK_FLAG_TYPE_P
;
501 p_sys
->i_flags
= BLOCK_FLAG_TYPE_B
;
502 p_sys
->b_frame
= true;
505 p_sys
->i_flags
= BLOCK_FLAG_TYPE_PB
;
509 while( bs_read( &s
, 1 ) ) i_modulo_time_base
++;
510 if( !bs_read1( &s
) ) return VLC_EGENERIC
; /* Marker */
512 /* VOP time increment */
513 i_time_increment_bits
= vlc_log2(p_sys
->i_fps_num
- 1) + 1;
514 if( i_time_increment_bits
< 1 ) i_time_increment_bits
= 1;
515 i_time_increment
= bs_read( &s
, i_time_increment_bits
);
517 /* Interpolate PTS/DTS */
518 if( !(p_sys
->i_flags
& BLOCK_FLAG_TYPE_B
) )
520 p_sys
->i_last_time_ref
= p_sys
->i_time_ref
;
522 (i_modulo_time_base
* p_sys
->i_fps_num
);
523 i_time_ref
= p_sys
->i_time_ref
;
527 i_time_ref
= p_sys
->i_last_time_ref
+
528 (i_modulo_time_base
* p_sys
->i_fps_num
);
532 msg_Err( p_dec
, "interp pts/dts (%lli,%lli), pts/dts (%lli,%lli)",
533 p_sys
->i_interpolated_pts
, p_sys
->i_interpolated_dts
,
534 p_vop
->i_pts
, p_vop
->i_dts
);
537 if( p_sys
->i_fps_num
< 5 && /* Work-around buggy streams */
538 p_dec
->fmt_in
.video
.i_frame_rate
> 0 &&
539 p_dec
->fmt_in
.video
.i_frame_rate_base
> 0 )
541 p_sys
->i_interpolated_pts
+= CLOCK_FREQ
*
542 p_dec
->fmt_in
.video
.i_frame_rate_base
/
543 p_dec
->fmt_in
.video
.i_frame_rate
;
545 else if( p_sys
->i_fps_num
)
546 p_sys
->i_interpolated_pts
+=
547 ( CLOCK_FREQ
* (i_time_ref
+ i_time_increment
-
548 p_sys
->i_last_time
- p_sys
->i_last_timeincr
) /
551 p_sys
->i_last_time
= i_time_ref
;
552 p_sys
->i_last_timeincr
= i_time_increment
;
554 /* Correct interpolated dts when we receive a new pts/dts */
555 if( p_vop
->i_pts
!= VLC_TS_INVALID
)
556 p_sys
->i_interpolated_pts
= p_vop
->i_pts
;
557 if( p_vop
->i_dts
!= VLC_TS_INVALID
)
558 p_sys
->i_interpolated_dts
= p_vop
->i_dts
;
560 if( (p_sys
->i_flags
& BLOCK_FLAG_TYPE_B
) || !p_sys
->b_frame
)
562 /* Trivial case (DTS == PTS) */
564 p_sys
->i_interpolated_dts
= p_sys
->i_interpolated_pts
;
566 if( p_vop
->i_pts
!= VLC_TS_INVALID
)
567 p_sys
->i_interpolated_dts
= p_vop
->i_pts
;
568 if( p_vop
->i_dts
!= VLC_TS_INVALID
)
569 p_sys
->i_interpolated_dts
= p_vop
->i_dts
;
571 p_sys
->i_interpolated_pts
= p_sys
->i_interpolated_dts
;
575 if( p_sys
->i_last_ref_pts
!= VLC_TS_INVALID
)
576 p_sys
->i_interpolated_dts
= p_sys
->i_last_ref_pts
;
578 p_sys
->i_last_ref_pts
= p_sys
->i_interpolated_pts
;
584 /* look at libavutil av_log2 ;) */
585 static int vlc_log2( unsigned int v
)
588 static const int vlc_log2_table
[16] =
590 0,0,1,1,2,2,2,2, 3,3,3,3,3,3,3,3
608 n
+= vlc_log2_table
[v
];