1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001, 2002, 2006 VLC authors and VideoLAN
6 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7 * Eric Petit <titer@videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_codec.h>
35 #include <vlc_block.h>
38 /*****************************************************************************
40 *****************************************************************************/
41 static int Open ( vlc_object_t
* );
42 static void Close( vlc_object_t
* );
45 set_category( CAT_SOUT
)
46 set_subcategory( SUBCAT_SOUT_PACKETIZER
)
47 set_description( N_("Copy packetizer") )
48 set_capability( "packetizer", 1 )
49 set_callbacks( Open
, Close
)
52 /*****************************************************************************
54 *****************************************************************************/
58 void (*pf_parse
)( decoder_t
*, block_t
* );
61 static block_t
*Packetize ( decoder_t
*, block_t
** );
62 static block_t
*PacketizeSub( decoder_t
*, block_t
** );
63 static void Flush( decoder_t
* );
65 static void ParseWMV3( decoder_t
*, block_t
* );
67 /*****************************************************************************
68 * Open: probe the packetizer and return score
69 *****************************************************************************
70 * Tries to launch a decoder and return score so that the interface is able
72 *****************************************************************************/
73 static int Open( vlc_object_t
*p_this
)
75 decoder_t
*p_dec
= (decoder_t
*)p_this
;
78 if( p_dec
->fmt_in
.i_cat
!= AUDIO_ES
&&
79 p_dec
->fmt_in
.i_cat
!= VIDEO_ES
&&
80 p_dec
->fmt_in
.i_cat
!= SPU_ES
)
82 msg_Err( p_dec
, "invalid ES type" );
86 p_dec
->p_sys
= p_sys
= malloc( sizeof(*p_sys
) );
87 if (unlikely(p_sys
== NULL
))
90 p_sys
->p_block
= NULL
;
91 switch( p_dec
->fmt_in
.i_codec
)
94 p_sys
->pf_parse
= ParseWMV3
;
97 p_sys
->pf_parse
= NULL
;
101 vlc_fourcc_t fcc
= p_dec
->fmt_in
.i_codec
;
102 /* Fix the value of the fourcc for audio */
103 if( p_dec
->fmt_in
.i_cat
== AUDIO_ES
)
105 fcc
= vlc_fourcc_GetCodecAudio( p_dec
->fmt_in
.i_codec
,
106 p_dec
->fmt_in
.audio
.i_bitspersample
);
109 msg_Err( p_dec
, "unknown raw audio sample size" );
115 /* Create the output format */
116 es_format_Copy( &p_dec
->fmt_out
, &p_dec
->fmt_in
);
117 p_dec
->fmt_out
.i_codec
= fcc
;
118 if( p_dec
->fmt_in
.i_cat
== SPU_ES
)
119 p_dec
->pf_packetize
= PacketizeSub
;
121 p_dec
->pf_packetize
= Packetize
;
122 p_dec
->pf_flush
= Flush
;
123 p_dec
->pf_get_cc
= NULL
;
128 /*****************************************************************************
130 *****************************************************************************/
131 static void Close( vlc_object_t
*p_this
)
133 decoder_t
*p_dec
= (decoder_t
*)p_this
;
134 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
138 block_ChainRelease( p_sys
->p_block
);
141 free( p_dec
->p_sys
);
144 static void Flush( decoder_t
*p_dec
)
146 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
147 block_t
*p_ret
= p_sys
->p_block
;
150 block_Release( p_ret
);
151 p_sys
->p_block
= NULL
;
155 /*****************************************************************************
156 * Packetize: packetize an unit (here copy a complete block )
157 *****************************************************************************/
158 static block_t
*Packetize ( decoder_t
*p_dec
, block_t
**pp_block
)
161 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
162 block_t
*p_ret
= p_sys
->p_block
;
164 if( pp_block
== NULL
|| *pp_block
== NULL
)
166 if( (*pp_block
)->i_flags
&(BLOCK_FLAG_CORRUPTED
) )
168 block_Release( *pp_block
);
175 if( p_block
->i_dts
== VLC_TICK_INVALID
)
177 p_block
->i_dts
= p_block
->i_pts
;
180 if( p_block
->i_dts
== VLC_TICK_INVALID
)
182 msg_Dbg( p_dec
, "need valid dts" );
183 block_Release( p_block
);
187 if( p_ret
!= NULL
&& p_block
->i_pts
> p_ret
->i_pts
)
189 if (p_dec
->fmt_in
.i_codec
!= VLC_CODEC_OPUS
)
190 p_ret
->i_length
= p_block
->i_pts
- p_ret
->i_pts
;
192 p_sys
->p_block
= p_block
;
194 if( p_ret
&& p_sys
->pf_parse
)
195 p_sys
->pf_parse( p_dec
, p_ret
);
199 /*****************************************************************************
200 * PacketizeSub: packetize an unit (here copy a complete block )
201 *****************************************************************************/
202 static block_t
*PacketizeSub( decoder_t
*p_dec
, block_t
**pp_block
)
206 if( pp_block
== NULL
|| *pp_block
== NULL
)
208 if( (*pp_block
)->i_flags
&(BLOCK_FLAG_CORRUPTED
) )
210 block_Release( *pp_block
);
217 if( p_block
->i_dts
== VLC_TICK_INVALID
)
219 p_block
->i_dts
= p_block
->i_pts
;
222 if( p_block
->i_dts
== VLC_TICK_INVALID
)
224 msg_Dbg( p_dec
, "need valid dts" );
225 block_Release( p_block
);
232 /* Parse WMV3 packet and extract frame type information */
233 static void ParseWMV3( decoder_t
*p_dec
, block_t
*p_block
)
237 /* Parse Sequence header */
238 bs_init( &s
, p_dec
->fmt_in
.p_extra
, p_dec
->fmt_in
.i_extra
);
239 if( bs_read( &s
, 2 ) == 3 )
242 const bool b_range_reduction
= bs_read( &s
, 1 );
243 const bool b_has_frames
= bs_read( &s
, 3 ) > 0;
245 const bool b_frame_interpolation
= bs_read( &s
, 1 );
249 /* Parse frame type */
250 bs_init( &s
, p_block
->p_buffer
, p_block
->i_buffer
);
251 bs_skip( &s
, b_frame_interpolation
+
255 p_block
->i_flags
&= ~BLOCK_FLAG_TYPE_MASK
;
256 if( bs_read( &s
, 1 ) )
257 p_block
->i_flags
|= BLOCK_FLAG_TYPE_P
;
258 else if( !b_has_frames
|| bs_read( &s
, 1 ) )
259 p_block
->i_flags
|= BLOCK_FLAG_TYPE_I
;
261 p_block
->i_flags
|= BLOCK_FLAG_TYPE_B
;