/src/vlc/modules/packetizer/copy.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * copy.c |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2001, 2002, 2006 VLC authors and VideoLAN |
5 | | * |
6 | | * Authors: Laurent Aimar <fenrir@via.ecp.fr> |
7 | | * Eric Petit <titer@videolan.org> |
8 | | * |
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. |
13 | | * |
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. |
18 | | * |
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 | | *****************************************************************************/ |
23 | | |
24 | | /***************************************************************************** |
25 | | * Preamble |
26 | | *****************************************************************************/ |
27 | | |
28 | | #ifdef HAVE_CONFIG_H |
29 | | # include "config.h" |
30 | | #endif |
31 | | |
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> |
37 | | |
38 | | /***************************************************************************** |
39 | | * Module descriptor |
40 | | *****************************************************************************/ |
41 | | static int Open ( vlc_object_t * ); |
42 | | static void Close( vlc_object_t * ); |
43 | | |
44 | 150 | vlc_module_begin () |
45 | 75 | set_subcategory( SUBCAT_SOUT_PACKETIZER ) |
46 | 75 | set_description( N_("Copy packetizer") ) |
47 | 75 | set_capability( "video packetizer", 1 ) |
48 | 150 | set_callbacks( Open, Close ) |
49 | 75 | add_submodule() |
50 | 75 | set_capability( "audio packetizer", 1 ) |
51 | 150 | set_callbacks( Open, Close ) |
52 | 75 | add_submodule() |
53 | 75 | set_capability( "spu packetizer", 1 ) |
54 | 150 | set_callbacks( Open, Close ) |
55 | 75 | vlc_module_end () |
56 | | |
57 | | /***************************************************************************** |
58 | | * Local prototypes |
59 | | *****************************************************************************/ |
60 | | typedef struct |
61 | | { |
62 | | block_t *p_block; |
63 | | void (*pf_parse)( decoder_t *, block_t * ); |
64 | | } decoder_sys_t; |
65 | | |
66 | | static block_t *Packetize ( decoder_t *, block_t ** ); |
67 | | static block_t *PacketizeSub( decoder_t *, block_t ** ); |
68 | | static void Flush( decoder_t * ); |
69 | | |
70 | | static void ParseWMV3( decoder_t *, block_t * ); |
71 | | |
72 | | /***************************************************************************** |
73 | | * Open: probe the packetizer and return score |
74 | | ***************************************************************************** |
75 | | * Tries to launch a decoder and return score so that the interface is able |
76 | | * to choose. |
77 | | *****************************************************************************/ |
78 | | static int Open( vlc_object_t *p_this ) |
79 | 2.15M | { |
80 | 2.15M | decoder_t *p_dec = (decoder_t*)p_this; |
81 | 2.15M | decoder_sys_t *p_sys; |
82 | | |
83 | 2.15M | if( p_dec->fmt_in->i_cat != AUDIO_ES && |
84 | 40.4k | p_dec->fmt_in->i_cat != VIDEO_ES && |
85 | 21.7k | p_dec->fmt_in->i_cat != SPU_ES ) |
86 | 0 | { |
87 | 0 | msg_Err( p_dec, "invalid ES type" ); |
88 | 0 | return VLC_EGENERIC; |
89 | 0 | } |
90 | | |
91 | 2.15M | p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) ); |
92 | 2.15M | if (unlikely(p_sys == NULL)) |
93 | 0 | return VLC_ENOMEM; |
94 | | |
95 | 2.15M | p_sys->p_block = NULL; |
96 | 2.15M | switch( p_dec->fmt_in->i_codec ) |
97 | 2.15M | { |
98 | 172 | case VLC_CODEC_WMV3: |
99 | 172 | p_sys->pf_parse = ParseWMV3; |
100 | 172 | break; |
101 | 2.15M | default: |
102 | 2.15M | p_sys->pf_parse = NULL; |
103 | 2.15M | break; |
104 | 2.15M | } |
105 | | |
106 | 2.15M | vlc_fourcc_t fcc = p_dec->fmt_in->i_codec; |
107 | | /* Fix the value of the fourcc for audio */ |
108 | 2.15M | if( p_dec->fmt_in->i_cat == AUDIO_ES ) |
109 | 2.11M | { |
110 | 2.11M | fcc = vlc_fourcc_GetCodecAudio( p_dec->fmt_in->i_codec, |
111 | 2.11M | p_dec->fmt_in->audio.i_bitspersample ); |
112 | 2.11M | if( !fcc ) |
113 | 318 | { |
114 | 318 | msg_Err( p_dec, "unknown raw audio sample size" ); |
115 | 318 | free( p_sys ); |
116 | 318 | return VLC_EGENERIC; |
117 | 318 | } |
118 | 2.11M | } |
119 | | |
120 | | /* Create the output format */ |
121 | 2.15M | es_format_Copy( &p_dec->fmt_out, p_dec->fmt_in ); |
122 | 2.15M | p_dec->fmt_out.i_codec = fcc; |
123 | 2.15M | if( p_dec->fmt_in->i_cat == SPU_ES ) |
124 | 21.7k | p_dec->pf_packetize = PacketizeSub; |
125 | 2.13M | else |
126 | 2.13M | p_dec->pf_packetize = Packetize; |
127 | 2.15M | p_dec->pf_flush = Flush; |
128 | 2.15M | p_dec->pf_get_cc = NULL; |
129 | | |
130 | 2.15M | return VLC_SUCCESS; |
131 | 2.15M | } |
132 | | |
133 | | /***************************************************************************** |
134 | | * Close: |
135 | | *****************************************************************************/ |
136 | | static void Close( vlc_object_t *p_this ) |
137 | 2.15M | { |
138 | 2.15M | decoder_t *p_dec = (decoder_t*)p_this; |
139 | 2.15M | decoder_sys_t *p_sys = p_dec->p_sys; |
140 | | |
141 | 2.15M | if( p_sys->p_block ) |
142 | 2.11M | { |
143 | 2.11M | block_ChainRelease( p_sys->p_block ); |
144 | 2.11M | } |
145 | | |
146 | 2.15M | free( p_dec->p_sys ); |
147 | 2.15M | } |
148 | | |
149 | | static void Flush( decoder_t *p_dec ) |
150 | 0 | { |
151 | 0 | decoder_sys_t *p_sys = p_dec->p_sys; |
152 | 0 | block_t *p_ret = p_sys->p_block; |
153 | 0 | if ( p_ret ) |
154 | 0 | { |
155 | 0 | block_Release( p_ret ); |
156 | 0 | p_sys->p_block = NULL; |
157 | 0 | } |
158 | 0 | } |
159 | | |
160 | | /***************************************************************************** |
161 | | * Packetize: packetize an unit (here copy a complete block ) |
162 | | *****************************************************************************/ |
163 | | static block_t *Packetize ( decoder_t *p_dec, block_t **pp_block ) |
164 | 133M | { |
165 | 133M | block_t *p_block; |
166 | 133M | decoder_sys_t *p_sys = p_dec->p_sys; |
167 | 133M | block_t *p_ret = p_sys->p_block; |
168 | | |
169 | 133M | if( pp_block == NULL || *pp_block == NULL ) |
170 | 66.8M | return NULL; |
171 | 66.8M | if( (*pp_block)->i_flags&(BLOCK_FLAG_CORRUPTED) ) |
172 | 0 | { |
173 | 0 | block_Release( *pp_block ); |
174 | 0 | return NULL; |
175 | 0 | } |
176 | | |
177 | 66.8M | p_block = *pp_block; |
178 | 66.8M | *pp_block = NULL; |
179 | | |
180 | 66.8M | if( p_block->i_dts == VLC_TICK_INVALID ) |
181 | 7.30k | { |
182 | 7.30k | p_block->i_dts = p_block->i_pts; |
183 | 7.30k | } |
184 | | |
185 | 66.8M | if( p_block->i_dts == VLC_TICK_INVALID ) |
186 | 7.23k | { |
187 | 7.23k | msg_Dbg( p_dec, "need valid dts" ); |
188 | 7.23k | block_Release( p_block ); |
189 | 7.23k | return NULL; |
190 | 7.23k | } |
191 | | |
192 | 66.8M | if( p_ret != NULL && p_block->i_pts > p_ret->i_pts ) |
193 | 64.1M | { |
194 | 64.1M | if (p_dec->fmt_in->i_codec != VLC_CODEC_OPUS) |
195 | 63.8M | p_ret->i_length = p_block->i_pts - p_ret->i_pts; |
196 | 64.1M | } |
197 | 66.8M | p_sys->p_block = p_block; |
198 | | |
199 | 66.8M | if( p_ret && p_sys->pf_parse ) |
200 | 248 | p_sys->pf_parse( p_dec, p_ret ); |
201 | 66.8M | return p_ret; |
202 | 66.8M | } |
203 | | |
204 | | /***************************************************************************** |
205 | | * PacketizeSub: packetize an unit (here copy a complete block ) |
206 | | *****************************************************************************/ |
207 | | static block_t *PacketizeSub( decoder_t *p_dec, block_t **pp_block ) |
208 | 1.31M | { |
209 | 1.31M | block_t *p_block; |
210 | | |
211 | 1.31M | if( pp_block == NULL || *pp_block == NULL ) |
212 | 663k | return NULL; |
213 | 652k | if( (*pp_block)->i_flags&(BLOCK_FLAG_CORRUPTED) ) |
214 | 2.49k | { |
215 | 2.49k | block_Release( *pp_block ); |
216 | 2.49k | return NULL; |
217 | 2.49k | } |
218 | | |
219 | 649k | p_block = *pp_block; |
220 | 649k | *pp_block = NULL; |
221 | | |
222 | 649k | if( p_block->i_dts == VLC_TICK_INVALID ) |
223 | 17.8k | { |
224 | 17.8k | p_block->i_dts = p_block->i_pts; |
225 | 17.8k | } |
226 | | |
227 | 649k | if( p_block->i_dts == VLC_TICK_INVALID ) |
228 | 7.57k | { |
229 | 7.57k | msg_Dbg( p_dec, "need valid dts" ); |
230 | 7.57k | block_Release( p_block ); |
231 | 7.57k | return NULL; |
232 | 7.57k | } |
233 | | |
234 | 642k | return p_block; |
235 | 649k | } |
236 | | |
237 | | /* Parse WMV3 packet and extract frame type information */ |
238 | | static void ParseWMV3( decoder_t *p_dec, block_t *p_block ) |
239 | 248 | { |
240 | 248 | bs_t s; |
241 | | |
242 | | /* Parse Sequence header */ |
243 | 248 | bs_init( &s, p_dec->fmt_in->p_extra, p_dec->fmt_in->i_extra ); |
244 | 248 | if( bs_read( &s, 2 ) == 3 ) |
245 | 0 | return; |
246 | 248 | bs_skip( &s, 22 ); |
247 | 248 | const bool b_range_reduction = bs_read( &s, 1 ); |
248 | 248 | const bool b_has_frames = bs_read( &s, 3 ) > 0; |
249 | 248 | bs_skip( &s, 2 ); |
250 | 248 | const bool b_frame_interpolation = bs_read( &s, 1 ); |
251 | 248 | if( bs_eof( &s ) ) |
252 | 3 | return; |
253 | | |
254 | | /* Parse frame type */ |
255 | 245 | bs_init( &s, p_block->p_buffer, p_block->i_buffer ); |
256 | 245 | bs_skip( &s, b_frame_interpolation + |
257 | 245 | 2 + |
258 | 245 | b_range_reduction ); |
259 | | |
260 | 245 | p_block->i_flags &= ~BLOCK_FLAG_TYPE_MASK; |
261 | 245 | if( bs_read( &s, 1 ) ) |
262 | 161 | p_block->i_flags |= BLOCK_FLAG_TYPE_P; |
263 | 84 | else if( !b_has_frames || bs_read( &s, 1 ) ) |
264 | 67 | p_block->i_flags |= BLOCK_FLAG_TYPE_I; |
265 | 17 | else |
266 | 17 | p_block->i_flags |= BLOCK_FLAG_TYPE_B; |
267 | 245 | } |
268 | | |