1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001, 2002, 2006 VLC authors and VideoLAN
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Eric Petit <titer@videolan.org>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_codec.h>
36 #include <vlc_block.h>
39 /*****************************************************************************
41 *****************************************************************************/
42 static int Open ( vlc_object_t
* );
43 static void Close( vlc_object_t
* );
46 set_category( CAT_SOUT
)
47 set_subcategory( SUBCAT_SOUT_PACKETIZER
)
48 set_description( N_("Copy packetizer") )
49 set_capability( "packetizer", 1 )
50 set_callbacks( Open
, Close
)
53 /*****************************************************************************
55 *****************************************************************************/
59 void (*pf_parse
)( decoder_t
*, block_t
* );
62 static block_t
*Packetize ( decoder_t
*, block_t
** );
63 static block_t
*PacketizeSub( decoder_t
*, block_t
** );
64 static void Flush( decoder_t
* );
66 static void ParseWMV3( decoder_t
*, block_t
* );
68 /*****************************************************************************
69 * Open: probe the packetizer and return score
70 *****************************************************************************
71 * Tries to launch a decoder and return score so that the interface is able
73 *****************************************************************************/
74 static int Open( vlc_object_t
*p_this
)
76 decoder_t
*p_dec
= (decoder_t
*)p_this
;
79 if( p_dec
->fmt_in
.i_cat
!= AUDIO_ES
&&
80 p_dec
->fmt_in
.i_cat
!= VIDEO_ES
&&
81 p_dec
->fmt_in
.i_cat
!= SPU_ES
)
83 msg_Err( p_dec
, "invalid ES type" );
87 p_dec
->p_sys
= p_sys
= malloc( sizeof(*p_sys
) );
88 if (unlikely(p_sys
== NULL
))
91 p_sys
->p_block
= NULL
;
92 switch( p_dec
->fmt_in
.i_codec
)
95 p_sys
->pf_parse
= ParseWMV3
;
98 p_sys
->pf_parse
= NULL
;
102 vlc_fourcc_t fcc
= p_dec
->fmt_in
.i_codec
;
103 /* Fix the value of the fourcc for audio */
104 if( p_dec
->fmt_in
.i_cat
== AUDIO_ES
)
106 fcc
= vlc_fourcc_GetCodecAudio( p_dec
->fmt_in
.i_codec
,
107 p_dec
->fmt_in
.audio
.i_bitspersample
);
110 msg_Err( p_dec
, "unknown raw audio sample size" );
116 /* Create the output format */
117 es_format_Copy( &p_dec
->fmt_out
, &p_dec
->fmt_in
);
118 p_dec
->fmt_out
.i_codec
= fcc
;
119 if( p_dec
->fmt_in
.i_cat
== SPU_ES
)
120 p_dec
->pf_packetize
= PacketizeSub
;
122 p_dec
->pf_packetize
= Packetize
;
123 p_dec
->pf_flush
= Flush
;
124 p_dec
->pf_get_cc
= NULL
;
129 /*****************************************************************************
131 *****************************************************************************/
132 static void Close( vlc_object_t
*p_this
)
134 decoder_t
*p_dec
= (decoder_t
*)p_this
;
135 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
139 block_ChainRelease( p_sys
->p_block
);
142 free( p_dec
->p_sys
);
145 static void Flush( decoder_t
*p_dec
)
147 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
148 block_t
*p_ret
= p_sys
->p_block
;
151 block_Release( p_ret
);
152 p_sys
->p_block
= NULL
;
156 /*****************************************************************************
157 * Packetize: packetize an unit (here copy a complete block )
158 *****************************************************************************/
159 static block_t
*Packetize ( decoder_t
*p_dec
, block_t
**pp_block
)
162 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
163 block_t
*p_ret
= p_sys
->p_block
;
165 if( pp_block
== NULL
|| *pp_block
== NULL
)
167 if( (*pp_block
)->i_flags
&(BLOCK_FLAG_CORRUPTED
) )
169 block_Release( *pp_block
);
176 if( p_block
->i_dts
== VLC_TICK_INVALID
)
178 p_block
->i_dts
= p_block
->i_pts
;
181 if( p_block
->i_dts
== VLC_TICK_INVALID
)
183 msg_Dbg( p_dec
, "need valid dts" );
184 block_Release( p_block
);
188 if( p_ret
!= NULL
&& p_block
->i_pts
> p_ret
->i_pts
)
190 if (p_dec
->fmt_in
.i_codec
!= VLC_CODEC_OPUS
)
191 p_ret
->i_length
= p_block
->i_pts
- p_ret
->i_pts
;
193 p_sys
->p_block
= p_block
;
195 if( p_ret
&& p_sys
->pf_parse
)
196 p_sys
->pf_parse( p_dec
, p_ret
);
200 /*****************************************************************************
201 * PacketizeSub: packetize an unit (here copy a complete block )
202 *****************************************************************************/
203 static block_t
*PacketizeSub( decoder_t
*p_dec
, block_t
**pp_block
)
207 if( pp_block
== NULL
|| *pp_block
== NULL
)
209 if( (*pp_block
)->i_flags
&(BLOCK_FLAG_CORRUPTED
) )
211 block_Release( *pp_block
);
218 if( p_block
->i_dts
== VLC_TICK_INVALID
)
220 p_block
->i_dts
= p_block
->i_pts
;
223 if( p_block
->i_dts
== VLC_TICK_INVALID
)
225 msg_Dbg( p_dec
, "need valid dts" );
226 block_Release( p_block
);
233 /* Parse WMV3 packet and extract frame type information */
234 static void ParseWMV3( decoder_t
*p_dec
, block_t
*p_block
)
238 /* Parse Sequence header */
239 bs_init( &s
, p_dec
->fmt_in
.p_extra
, p_dec
->fmt_in
.i_extra
);
240 if( bs_read( &s
, 2 ) == 3 )
243 const bool b_range_reduction
= bs_read( &s
, 1 );
244 const bool b_has_frames
= bs_read( &s
, 3 ) > 0;
246 const bool b_frame_interpolation
= bs_read( &s
, 1 );
250 /* Parse frame type */
251 bs_init( &s
, p_block
->p_buffer
, p_block
->i_buffer
);
252 bs_skip( &s
, b_frame_interpolation
+
256 p_block
->i_flags
&= ~BLOCK_FLAG_TYPE_MASK
;
257 if( bs_read( &s
, 1 ) )
258 p_block
->i_flags
|= BLOCK_FLAG_TYPE_P
;
259 else if( !b_has_frames
|| bs_read( &s
, 1 ) )
260 p_block
->i_flags
|= BLOCK_FLAG_TYPE_I
;
262 p_block
->i_flags
|= BLOCK_FLAG_TYPE_B
;