qml: Create MediaGroupDisplay
[vlc.git] / modules / packetizer / copy.c
blob2207bc73f0d8659c57fb998883a424000d6a1a68
1 /*****************************************************************************
2 * copy.c
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 /*****************************************************************************
25 * Preamble
26 *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_codec.h>
35 #include <vlc_block.h>
36 #include <vlc_bits.h>
38 /*****************************************************************************
39 * Module descriptor
40 *****************************************************************************/
41 static int Open ( vlc_object_t * );
42 static void Close( vlc_object_t * );
44 vlc_module_begin ()
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 )
50 vlc_module_end ()
52 /*****************************************************************************
53 * Local prototypes
54 *****************************************************************************/
55 typedef struct
57 block_t *p_block;
58 void (*pf_parse)( decoder_t *, block_t * );
59 } decoder_sys_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
71 * to choose.
72 *****************************************************************************/
73 static int Open( vlc_object_t *p_this )
75 decoder_t *p_dec = (decoder_t*)p_this;
76 decoder_sys_t *p_sys;
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" );
83 return VLC_EGENERIC;
86 p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) );
87 if (unlikely(p_sys == NULL))
88 return VLC_ENOMEM;
90 p_sys->p_block = NULL;
91 switch( p_dec->fmt_in.i_codec )
93 case VLC_CODEC_WMV3:
94 p_sys->pf_parse = ParseWMV3;
95 break;
96 default:
97 p_sys->pf_parse = NULL;
98 break;
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 );
107 if( !fcc )
109 msg_Err( p_dec, "unknown raw audio sample size" );
110 free( p_sys );
111 return VLC_EGENERIC;
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;
120 else
121 p_dec->pf_packetize = Packetize;
122 p_dec->pf_flush = Flush;
123 p_dec->pf_get_cc = NULL;
125 return VLC_SUCCESS;
128 /*****************************************************************************
129 * Close:
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;
136 if( p_sys->p_block )
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;
148 if ( p_ret )
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 )
160 block_t *p_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 )
165 return NULL;
166 if( (*pp_block)->i_flags&(BLOCK_FLAG_CORRUPTED) )
168 block_Release( *pp_block );
169 return NULL;
172 p_block = *pp_block;
173 *pp_block = NULL;
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 );
184 return NULL;
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 );
196 return 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 )
204 block_t *p_block;
206 if( pp_block == NULL || *pp_block == NULL )
207 return NULL;
208 if( (*pp_block)->i_flags&(BLOCK_FLAG_CORRUPTED) )
210 block_Release( *pp_block );
211 return NULL;
214 p_block = *pp_block;
215 *pp_block = NULL;
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 );
226 return NULL;
229 return p_block;
232 /* Parse WMV3 packet and extract frame type information */
233 static void ParseWMV3( decoder_t *p_dec, block_t *p_block )
235 bs_t s;
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 )
240 return;
241 bs_skip( &s, 22 );
242 const bool b_range_reduction = bs_read( &s, 1 );
243 const bool b_has_frames = bs_read( &s, 3 ) > 0;
244 bs_skip( &s, 2 );
245 const bool b_frame_interpolation = bs_read( &s, 1 );
246 if( bs_eof( &s ) )
247 return;
249 /* Parse frame type */
250 bs_init( &s, p_block->p_buffer, p_block->i_buffer );
251 bs_skip( &s, b_frame_interpolation +
253 b_range_reduction );
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;
260 else
261 p_block->i_flags |= BLOCK_FLAG_TYPE_B;