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
;
365 if( p_vol
[0] == 0x00 && p_vol
[1] == 0x00 && p_vol
[2] == 0x01 &&
366 p_vol
[3] >= 0x20 && p_vol
[3] <= 0x2f ) break;
369 if( i_vol
<= 4 ) return VLC_EGENERIC
;
372 bs_init( &s
, &p_vol
[4], i_vol
- 4 );
374 bs_skip( &s
, 1 ); /* random access */
375 bs_skip( &s
, 8 ); /* vo_type */
378 i_vo_ver_id
= bs_read( &s
, 4 );
385 i_ar
= bs_read( &s
, 4 );
388 bs_skip( &s
, 8 ); /* ar_width */
389 bs_skip( &s
, 8 ); /* ar_height */
393 /* vol control parameter */
394 bs_skip( &s
, 2 ); /* chroma_format */
395 bs_read1( &s
); /* low_delay */
408 /* shape 0->RECT, 1->BIN, 2->BIN_ONLY, 3->GRAY */
409 i_shape
= bs_read( &s
, 2 );
410 if( i_shape
== 3 && i_vo_ver_id
!= 1 )
415 if( !bs_read1( &s
) ) return VLC_EGENERIC
; /* Marker */
417 p_sys
->i_fps_num
= bs_read( &s
, 16 ); /* Time increment resolution*/
418 if( !p_sys
->i_fps_num
) p_sys
->i_fps_num
= 1;
420 if( !bs_read1( &s
) ) return VLC_EGENERIC
; /* Marker */
424 int i_time_increment_bits
= vlc_log2( p_sys
->i_fps_num
- 1 ) + 1;
426 if( i_time_increment_bits
< 1 ) i_time_increment_bits
= 1;
428 p_sys
->i_fps_den
= bs_read( &s
, i_time_increment_bits
);
433 fmt
->video
.i_width
= bs_read( &s
, 13 );
435 fmt
->video
.i_height
= bs_read( &s
, 13 );
442 static int ParseVO( decoder_t
*p_dec
, block_t
*p_vo
)
445 bs_init( &s
, &p_vo
->p_buffer
[4], p_vo
->i_buffer
- 4 );
449 const uint8_t visual_object_type
= bs_read( &s
, 4 );
450 if( visual_object_type
== 1 /* video ID */ ||
451 visual_object_type
== 2 /* still texture ID */ )
453 uint8_t colour_primaries
= 1;
454 uint8_t colour_xfer
= 1;
455 uint8_t colour_matrix_coeff
= 1;
456 uint8_t full_range
= 0;
457 if( bs_read1( &s
) ) /* video_signal_type */
460 full_range
= bs_read( &s
, 1 );
461 if( bs_read( &s
, 1 ) ) /* colour description */
463 colour_primaries
= bs_read( &s
, 8 );
464 colour_xfer
= bs_read( &s
, 8 );
465 colour_matrix_coeff
= bs_read( &s
, 8 );
469 if( p_dec
->fmt_in
.video
.primaries
== COLOR_PRIMARIES_UNDEF
)
471 p_dec
->fmt_out
.video
.primaries
= hxxx_colour_primaries_to_vlc( colour_primaries
);
472 p_dec
->fmt_out
.video
.transfer
= hxxx_transfer_characteristics_to_vlc( colour_xfer
);
473 p_dec
->fmt_out
.video
.space
= hxxx_matrix_coeffs_to_vlc( colour_matrix_coeff
);
474 p_dec
->fmt_out
.video
.b_color_range_full
= full_range
;
481 static int ParseVOP( decoder_t
*p_dec
, block_t
*p_vop
)
483 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
484 int64_t i_time_increment
, i_time_ref
;
485 int i_modulo_time_base
= 0, i_time_increment_bits
;
488 bs_init( &s
, &p_vop
->p_buffer
[4], p_vop
->i_buffer
- 4 );
490 switch( bs_read( &s
, 2 ) )
493 p_sys
->i_flags
= BLOCK_FLAG_TYPE_I
;
496 p_sys
->i_flags
= BLOCK_FLAG_TYPE_P
;
499 p_sys
->i_flags
= BLOCK_FLAG_TYPE_B
;
500 p_sys
->b_frame
= true;
503 p_sys
->i_flags
= BLOCK_FLAG_TYPE_PB
;
507 while( bs_read( &s
, 1 ) ) i_modulo_time_base
++;
508 if( !bs_read1( &s
) ) return VLC_EGENERIC
; /* Marker */
510 /* VOP time increment */
511 i_time_increment_bits
= vlc_log2(p_dec
->p_sys
->i_fps_num
- 1) + 1;
512 if( i_time_increment_bits
< 1 ) i_time_increment_bits
= 1;
513 i_time_increment
= bs_read( &s
, i_time_increment_bits
);
515 /* Interpolate PTS/DTS */
516 if( !(p_sys
->i_flags
& BLOCK_FLAG_TYPE_B
) )
518 p_sys
->i_last_time_ref
= p_sys
->i_time_ref
;
520 (i_modulo_time_base
* p_dec
->p_sys
->i_fps_num
);
521 i_time_ref
= p_sys
->i_time_ref
;
525 i_time_ref
= p_sys
->i_last_time_ref
+
526 (i_modulo_time_base
* p_dec
->p_sys
->i_fps_num
);
530 msg_Err( p_dec
, "interp pts/dts (%lli,%lli), pts/dts (%lli,%lli)",
531 p_sys
->i_interpolated_pts
, p_sys
->i_interpolated_dts
,
532 p_vop
->i_pts
, p_vop
->i_dts
);
535 if( p_dec
->p_sys
->i_fps_num
< 5 && /* Work-around buggy streams */
536 p_dec
->fmt_in
.video
.i_frame_rate
> 0 &&
537 p_dec
->fmt_in
.video
.i_frame_rate_base
> 0 )
539 p_sys
->i_interpolated_pts
+= CLOCK_FREQ
*
540 p_dec
->fmt_in
.video
.i_frame_rate_base
/
541 p_dec
->fmt_in
.video
.i_frame_rate
;
543 else if( p_dec
->p_sys
->i_fps_num
)
544 p_sys
->i_interpolated_pts
+=
545 ( CLOCK_FREQ
* (i_time_ref
+ i_time_increment
-
546 p_sys
->i_last_time
- p_sys
->i_last_timeincr
) /
547 p_dec
->p_sys
->i_fps_num
);
549 p_sys
->i_last_time
= i_time_ref
;
550 p_sys
->i_last_timeincr
= i_time_increment
;
552 /* Correct interpolated dts when we receive a new pts/dts */
553 if( p_vop
->i_pts
> VLC_TS_INVALID
)
554 p_sys
->i_interpolated_pts
= p_vop
->i_pts
;
555 if( p_vop
->i_dts
> VLC_TS_INVALID
)
556 p_sys
->i_interpolated_dts
= p_vop
->i_dts
;
558 if( (p_sys
->i_flags
& BLOCK_FLAG_TYPE_B
) || !p_sys
->b_frame
)
560 /* Trivial case (DTS == PTS) */
562 p_sys
->i_interpolated_dts
= p_sys
->i_interpolated_pts
;
564 if( p_vop
->i_pts
> VLC_TS_INVALID
)
565 p_sys
->i_interpolated_dts
= p_vop
->i_pts
;
566 if( p_vop
->i_dts
> VLC_TS_INVALID
)
567 p_sys
->i_interpolated_dts
= p_vop
->i_dts
;
569 p_sys
->i_interpolated_pts
= p_sys
->i_interpolated_dts
;
573 if( p_sys
->i_last_ref_pts
> VLC_TS_INVALID
)
574 p_sys
->i_interpolated_dts
= p_sys
->i_last_ref_pts
;
576 p_sys
->i_last_ref_pts
= p_sys
->i_interpolated_pts
;
582 /* look at libavutil av_log2 ;) */
583 static int vlc_log2( unsigned int v
)
586 static const int vlc_log2_table
[16] =
588 0,0,1,1,2,2,2,2, 3,3,3,3,3,3,3,3
606 n
+= vlc_log2_table
[v
];