1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001, 2002, 2006 the VideoLAN team
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
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 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 General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, 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
** );
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 if( p_dec
->fmt_in
.i_cat
== SPU_ES
)
87 p_dec
->pf_packetize
= PacketizeSub
;
89 p_dec
->pf_packetize
= Packetize
;
91 /* Create the output format */
92 es_format_Copy( &p_dec
->fmt_out
, &p_dec
->fmt_in
);
94 /* Fix the value of the fourcc for audio */
95 if( p_dec
->fmt_in
.i_cat
== AUDIO_ES
)
97 p_dec
->fmt_out
.i_codec
= vlc_fourcc_GetCodecAudio( p_dec
->fmt_in
.i_codec
,
98 p_dec
->fmt_in
.audio
.i_bitspersample
);
99 if( !p_dec
->fmt_out
.i_codec
)
101 msg_Err( p_dec
, "unknown raw audio sample size" );
106 p_dec
->p_sys
= p_sys
= malloc( sizeof(*p_sys
) );
107 p_sys
->p_block
= NULL
;
108 switch( p_dec
->fmt_in
.i_codec
)
111 p_sys
->pf_parse
= ParseWMV3
;
114 p_sys
->pf_parse
= NULL
;
121 /*****************************************************************************
123 *****************************************************************************/
124 static void Close( vlc_object_t
*p_this
)
126 decoder_t
*p_dec
= (decoder_t
*)p_this
;
128 if( p_dec
->p_sys
->p_block
)
130 block_ChainRelease( p_dec
->p_sys
->p_block
);
133 es_format_Clean( &p_dec
->fmt_out
);
134 free( p_dec
->p_sys
);
137 /*****************************************************************************
138 * Packetize: packetize an unit (here copy a complete block )
139 *****************************************************************************/
140 static block_t
*Packetize ( decoder_t
*p_dec
, block_t
**pp_block
)
143 block_t
*p_ret
= p_dec
->p_sys
->p_block
;
145 if( pp_block
== NULL
|| *pp_block
== NULL
)
147 if( (*pp_block
)->i_flags
&(BLOCK_FLAG_DISCONTINUITY
|BLOCK_FLAG_CORRUPTED
) )
149 block_Release( *pp_block
);
156 if( p_block
->i_dts
<= VLC_TS_INVALID
)
158 p_block
->i_dts
= p_block
->i_pts
;
161 if( p_block
->i_dts
<= VLC_TS_INVALID
)
163 msg_Dbg( p_dec
, "need valid dts" );
164 block_Release( p_block
);
168 if( p_ret
!= NULL
&& p_block
->i_pts
> p_ret
->i_pts
)
170 p_ret
->i_length
= p_block
->i_pts
- p_ret
->i_pts
;
172 p_dec
->p_sys
->p_block
= p_block
;
174 if( p_ret
&& p_dec
->p_sys
->pf_parse
)
175 p_dec
->p_sys
->pf_parse( p_dec
, p_ret
);
179 /*****************************************************************************
180 * PacketizeSub: packetize an unit (here copy a complete block )
181 *****************************************************************************/
182 static block_t
*PacketizeSub( decoder_t
*p_dec
, block_t
**pp_block
)
186 if( pp_block
== NULL
|| *pp_block
== NULL
)
188 if( (*pp_block
)->i_flags
&(BLOCK_FLAG_DISCONTINUITY
|BLOCK_FLAG_CORRUPTED
) )
190 block_Release( *pp_block
);
197 if( p_block
->i_dts
<= VLC_TS_INVALID
)
199 p_block
->i_dts
= p_block
->i_pts
;
202 if( p_block
->i_dts
<= VLC_TS_INVALID
)
204 msg_Dbg( p_dec
, "need valid dts" );
205 block_Release( p_block
);
212 /* Parse WMV3 packet and extract frame type information */
213 static void ParseWMV3( decoder_t
*p_dec
, block_t
*p_block
)
217 /* Parse Sequence header */
218 bs_init( &s
, p_dec
->fmt_in
.p_extra
, p_dec
->fmt_in
.i_extra
);
219 if( bs_read( &s
, 2 ) == 3 )
222 const bool b_range_reduction
= bs_read( &s
, 1 );
223 const bool b_has_frames
= bs_read( &s
, 3 ) > 0;
225 const bool b_frame_interpolation
= bs_read( &s
, 1 );
229 /* Parse frame type */
230 bs_init( &s
, p_block
->p_buffer
, p_block
->i_buffer
);
231 bs_skip( &s
, b_frame_interpolation
+
235 p_block
->i_flags
&= ~BLOCK_FLAG_TYPE_MASK
;
236 if( bs_read( &s
, 1 ) )
237 p_block
->i_flags
|= BLOCK_FLAG_TYPE_P
;
238 else if( !b_has_frames
|| bs_read( &s
, 1 ) )
239 p_block
->i_flags
|= BLOCK_FLAG_TYPE_I
;
241 p_block
->i_flags
|= BLOCK_FLAG_TYPE_B
;