/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 | 104 | vlc_module_begin () |
45 | 52 | set_subcategory( SUBCAT_SOUT_PACKETIZER ) |
46 | 52 | set_description( N_("Copy packetizer") ) |
47 | 52 | set_capability( "video packetizer", 1 ) |
48 | 104 | set_callbacks( Open, Close ) |
49 | 52 | add_submodule() |
50 | 52 | set_capability( "audio packetizer", 1 ) |
51 | 104 | set_callbacks( Open, Close ) |
52 | 52 | add_submodule() |
53 | 52 | set_capability( "spu packetizer", 1 ) |
54 | 104 | set_callbacks( Open, Close ) |
55 | 52 | 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 | 1.91M | { |
80 | 1.91M | decoder_t *p_dec = (decoder_t*)p_this; |
81 | 1.91M | decoder_sys_t *p_sys; |
82 | | |
83 | 1.91M | if( p_dec->fmt_in->i_cat != AUDIO_ES && |
84 | 44.8k | p_dec->fmt_in->i_cat != VIDEO_ES && |
85 | 19.0k | 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 | 1.91M | p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) ); |
92 | 1.91M | if (unlikely(p_sys == NULL)) |
93 | 0 | return VLC_ENOMEM; |
94 | | |
95 | 1.91M | p_sys->p_block = NULL; |
96 | 1.91M | switch( p_dec->fmt_in->i_codec ) |
97 | 1.91M | { |
98 | 241 | case VLC_CODEC_WMV3: |
99 | 241 | p_sys->pf_parse = ParseWMV3; |
100 | 241 | break; |
101 | 1.91M | default: |
102 | 1.91M | p_sys->pf_parse = NULL; |
103 | 1.91M | break; |
104 | 1.91M | } |
105 | | |
106 | 1.91M | vlc_fourcc_t fcc = p_dec->fmt_in->i_codec; |
107 | | /* Fix the value of the fourcc for audio */ |
108 | 1.91M | if( p_dec->fmt_in->i_cat == AUDIO_ES ) |
109 | 1.86M | { |
110 | 1.86M | fcc = vlc_fourcc_GetCodecAudio( p_dec->fmt_in->i_codec, |
111 | 1.86M | p_dec->fmt_in->audio.i_bitspersample ); |
112 | 1.86M | if( !fcc ) |
113 | 1.20k | { |
114 | 1.20k | msg_Err( p_dec, "unknown raw audio sample size" ); |
115 | 1.20k | free( p_sys ); |
116 | 1.20k | return VLC_EGENERIC; |
117 | 1.20k | } |
118 | 1.86M | } |
119 | | |
120 | | /* Create the output format */ |
121 | 1.91M | es_format_Copy( &p_dec->fmt_out, p_dec->fmt_in ); |
122 | 1.91M | p_dec->fmt_out.i_codec = fcc; |
123 | 1.91M | if( p_dec->fmt_in->i_cat == SPU_ES ) |
124 | 19.0k | p_dec->pf_packetize = PacketizeSub; |
125 | 1.89M | else |
126 | 1.89M | p_dec->pf_packetize = Packetize; |
127 | 1.91M | p_dec->pf_flush = Flush; |
128 | 1.91M | p_dec->pf_get_cc = NULL; |
129 | | |
130 | 1.91M | return VLC_SUCCESS; |
131 | 1.91M | } |
132 | | |
133 | | /***************************************************************************** |
134 | | * Close: |
135 | | *****************************************************************************/ |
136 | | static void Close( vlc_object_t *p_this ) |
137 | 1.91M | { |
138 | 1.91M | decoder_t *p_dec = (decoder_t*)p_this; |
139 | 1.91M | decoder_sys_t *p_sys = p_dec->p_sys; |
140 | | |
141 | 1.91M | if( p_sys->p_block ) |
142 | 1.85M | { |
143 | 1.85M | block_ChainRelease( p_sys->p_block ); |
144 | 1.85M | } |
145 | | |
146 | 1.91M | free( p_dec->p_sys ); |
147 | 1.91M | } |
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 | 93.7M | { |
165 | 93.7M | block_t *p_block; |
166 | 93.7M | decoder_sys_t *p_sys = p_dec->p_sys; |
167 | 93.7M | block_t *p_ret = p_sys->p_block; |
168 | | |
169 | 93.7M | if( pp_block == NULL || *pp_block == NULL ) |
170 | 46.2M | return NULL; |
171 | 47.4M | if( (*pp_block)->i_flags&(BLOCK_FLAG_CORRUPTED) ) |
172 | 0 | { |
173 | 0 | block_Release( *pp_block ); |
174 | 0 | return NULL; |
175 | 0 | } |
176 | | |
177 | 47.4M | p_block = *pp_block; |
178 | 47.4M | *pp_block = NULL; |
179 | | |
180 | 47.4M | if( p_block->i_dts == VLC_TICK_INVALID ) |
181 | 90.3k | { |
182 | 90.3k | p_block->i_dts = p_block->i_pts; |
183 | 90.3k | } |
184 | | |
185 | 47.4M | if( p_block->i_dts == VLC_TICK_INVALID ) |
186 | 90.2k | { |
187 | 90.2k | msg_Dbg( p_dec, "need valid dts" ); |
188 | 90.2k | block_Release( p_block ); |
189 | 90.2k | return NULL; |
190 | 90.2k | } |
191 | | |
192 | 47.3M | if( p_ret != NULL && p_block->i_pts > p_ret->i_pts ) |
193 | 45.0M | { |
194 | 45.0M | if (p_dec->fmt_in->i_codec != VLC_CODEC_OPUS) |
195 | 44.8M | p_ret->i_length = p_block->i_pts - p_ret->i_pts; |
196 | 45.0M | } |
197 | 47.3M | p_sys->p_block = p_block; |
198 | | |
199 | 47.3M | if( p_ret && p_sys->pf_parse ) |
200 | 199 | p_sys->pf_parse( p_dec, p_ret ); |
201 | 47.3M | return p_ret; |
202 | 47.4M | } |
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.74M | { |
209 | 1.74M | block_t *p_block; |
210 | | |
211 | 1.74M | if( pp_block == NULL || *pp_block == NULL ) |
212 | 880k | return NULL; |
213 | 864k | if( (*pp_block)->i_flags&(BLOCK_FLAG_CORRUPTED) ) |
214 | 995 | { |
215 | 995 | block_Release( *pp_block ); |
216 | 995 | return NULL; |
217 | 995 | } |
218 | | |
219 | 863k | p_block = *pp_block; |
220 | 863k | *pp_block = NULL; |
221 | | |
222 | 863k | if( p_block->i_dts == VLC_TICK_INVALID ) |
223 | 10.8k | { |
224 | 10.8k | p_block->i_dts = p_block->i_pts; |
225 | 10.8k | } |
226 | | |
227 | 863k | if( p_block->i_dts == VLC_TICK_INVALID ) |
228 | 1.32k | { |
229 | 1.32k | msg_Dbg( p_dec, "need valid dts" ); |
230 | 1.32k | block_Release( p_block ); |
231 | 1.32k | return NULL; |
232 | 1.32k | } |
233 | | |
234 | 862k | return p_block; |
235 | 863k | } |
236 | | |
237 | | /* Parse WMV3 packet and extract frame type information */ |
238 | | static void ParseWMV3( decoder_t *p_dec, block_t *p_block ) |
239 | 199 | { |
240 | 199 | bs_t s; |
241 | | |
242 | | /* Parse Sequence header */ |
243 | 199 | bs_init( &s, p_dec->fmt_in->p_extra, p_dec->fmt_in->i_extra ); |
244 | 199 | if( bs_read( &s, 2 ) == 3 ) |
245 | 0 | return; |
246 | 199 | bs_skip( &s, 22 ); |
247 | 199 | const bool b_range_reduction = bs_read( &s, 1 ); |
248 | 199 | const bool b_has_frames = bs_read( &s, 3 ) > 0; |
249 | 199 | bs_skip( &s, 2 ); |
250 | 199 | const bool b_frame_interpolation = bs_read( &s, 1 ); |
251 | 199 | if( bs_eof( &s ) ) |
252 | 0 | return; |
253 | | |
254 | | /* Parse frame type */ |
255 | 199 | bs_init( &s, p_block->p_buffer, p_block->i_buffer ); |
256 | 199 | bs_skip( &s, b_frame_interpolation + |
257 | 199 | 2 + |
258 | 199 | b_range_reduction ); |
259 | | |
260 | 199 | p_block->i_flags &= ~BLOCK_FLAG_TYPE_MASK; |
261 | 199 | if( bs_read( &s, 1 ) ) |
262 | 142 | p_block->i_flags |= BLOCK_FLAG_TYPE_P; |
263 | 57 | else if( !b_has_frames || bs_read( &s, 1 ) ) |
264 | 56 | p_block->i_flags |= BLOCK_FLAG_TYPE_I; |
265 | 1 | else |
266 | 1 | p_block->i_flags |= BLOCK_FLAG_TYPE_B; |
267 | 199 | } |
268 | | |