00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <vlc/vlc.h>
00028 #include <vlc/decoder.h>
00029 #include <vlc/input.h>
00030
00031 #include <ogg/ogg.h>
00032 #include <speex/speex.h>
00033 #include <speex/speex_header.h>
00034 #include <speex/speex_stereo.h>
00035 #include <speex/speex_callbacks.h>
00036
00037
00038
00039
00040 struct decoder_sys_t
00041 {
00042
00043 vlc_bool_t b_packetizer;
00044
00045
00046
00047
00048 int i_headers;
00049 int i_frame_in_packet;
00050
00051
00052
00053
00054 SpeexBits bits;
00055 SpeexHeader *p_header;
00056 SpeexStereoState stereo;
00057 void *p_state;
00058
00059
00060
00061
00062 audio_date_t end_date;
00063
00064 };
00065
00066 static int pi_channels_maps[6] =
00067 {
00068 0,
00069 AOUT_CHAN_CENTER, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
00070 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
00071 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
00072 | AOUT_CHAN_REARRIGHT,
00073 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00074 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
00075 };
00076
00077
00078
00079
00080 static int OpenDecoder ( vlc_object_t * );
00081 static int OpenPacketizer( vlc_object_t * );
00082 static void CloseDecoder ( vlc_object_t * );
00083
00084 static void *DecodeBlock ( decoder_t *, block_t ** );
00085 static int ProcessHeaders( decoder_t * );
00086 static int ProcessInitialHeader ( decoder_t *, ogg_packet * );
00087 static void *ProcessPacket( decoder_t *, ogg_packet *, block_t ** );
00088
00089 static aout_buffer_t *DecodePacket( decoder_t *, ogg_packet * );
00090 static block_t *SendPacket( decoder_t *, ogg_packet *, block_t * );
00091
00092 static void ParseSpeexComments( decoder_t *, ogg_packet * );
00093
00094 static int OpenEncoder ( vlc_object_t * );
00095 static void CloseEncoder ( vlc_object_t * );
00096 static block_t *Encode ( encoder_t *, aout_buffer_t * );
00097
00098
00099
00100
00101 vlc_module_begin();
00102 set_category( CAT_INPUT );
00103 set_subcategory( SUBCAT_INPUT_ACODEC );
00104
00105 set_description( _("Speex audio decoder") );
00106 set_capability( "decoder", 100 );
00107 set_callbacks( OpenDecoder, CloseDecoder );
00108
00109 add_submodule();
00110 set_description( _("Speex audio packetizer") );
00111 set_capability( "packetizer", 100 );
00112 set_callbacks( OpenPacketizer, CloseDecoder );
00113
00114 add_submodule();
00115 set_description( _("Speex audio encoder") );
00116 set_capability( "encoder", 100 );
00117 set_callbacks( OpenEncoder, CloseEncoder );
00118 vlc_module_end();
00119
00120
00121
00122
00123 static int OpenDecoder( vlc_object_t *p_this )
00124 {
00125 decoder_t *p_dec = (decoder_t*)p_this;
00126 decoder_sys_t *p_sys = p_dec->p_sys;
00127
00128 if( p_dec->fmt_in.i_codec != VLC_FOURCC('s','p','x',' ') )
00129 {
00130 return VLC_EGENERIC;
00131 }
00132
00133
00134 if( ( p_dec->p_sys = p_sys =
00135 (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
00136 {
00137 msg_Err( p_dec, "out of memory" );
00138 return VLC_EGENERIC;
00139 }
00140 p_dec->p_sys->b_packetizer = VLC_FALSE;
00141
00142 aout_DateSet( &p_sys->end_date, 0 );
00143
00144
00145 p_dec->fmt_out.i_cat = AUDIO_ES;
00146 p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
00147
00148
00149 p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
00150 DecodeBlock;
00151 p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **))
00152 DecodeBlock;
00153
00154 p_sys->i_headers = 0;
00155 p_sys->p_state = NULL;
00156 p_sys->p_header = NULL;
00157 p_sys->i_frame_in_packet = 0;
00158
00159 return VLC_SUCCESS;
00160 }
00161
00162 static int OpenPacketizer( vlc_object_t *p_this )
00163 {
00164 decoder_t *p_dec = (decoder_t*)p_this;
00165
00166 int i_ret = OpenDecoder( p_this );
00167
00168 if( i_ret == VLC_SUCCESS )
00169 {
00170 p_dec->p_sys->b_packetizer = VLC_TRUE;
00171 p_dec->fmt_out.i_codec = VLC_FOURCC('s','p','x',' ');
00172 }
00173
00174 return i_ret;
00175 }
00176
00177
00178
00179
00180
00181
00182 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
00183 {
00184 decoder_sys_t *p_sys = p_dec->p_sys;
00185 ogg_packet oggpacket;
00186
00187 if( !pp_block ) return NULL;
00188
00189 if( *pp_block )
00190 {
00191
00192 oggpacket.packet = (*pp_block)->p_buffer;
00193 oggpacket.bytes = (*pp_block)->i_buffer;
00194 }
00195 else
00196 {
00197 if( p_sys->b_packetizer ) return NULL;
00198
00199
00200 oggpacket.packet = NULL;
00201 oggpacket.bytes = 0;
00202 }
00203
00204 oggpacket.granulepos = -1;
00205 oggpacket.b_o_s = 0;
00206 oggpacket.e_o_s = 0;
00207 oggpacket.packetno = 0;
00208
00209
00210 if( p_sys->i_headers == 0 && p_dec->fmt_in.i_extra )
00211 {
00212
00213 p_sys->i_headers = 2;
00214 }
00215 else if( oggpacket.bytes && p_sys->i_headers < 2 )
00216 {
00217
00218 uint8_t *p_extra;
00219
00220 p_dec->fmt_in.p_extra =
00221 realloc( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra +
00222 oggpacket.bytes + 2 );
00223 p_extra = p_dec->fmt_in.p_extra + p_dec->fmt_in.i_extra;
00224 *(p_extra++) = oggpacket.bytes >> 8;
00225 *(p_extra++) = oggpacket.bytes & 0xFF;
00226
00227 memcpy( p_extra, oggpacket.packet, oggpacket.bytes );
00228 p_dec->fmt_in.i_extra += oggpacket.bytes + 2;
00229
00230 block_Release( *pp_block );
00231 p_sys->i_headers++;
00232 return NULL;
00233 }
00234
00235 if( p_sys->i_headers == 2 )
00236 {
00237 if( ProcessHeaders( p_dec ) != VLC_SUCCESS )
00238 {
00239 p_sys->i_headers = 0;
00240 p_dec->fmt_in.i_extra = 0;
00241 block_Release( *pp_block );
00242 return NULL;
00243 }
00244 else p_sys->i_headers++;
00245 }
00246
00247 return ProcessPacket( p_dec, &oggpacket, pp_block );
00248 }
00249
00250
00251
00252
00253 static int ProcessHeaders( decoder_t *p_dec )
00254 {
00255 decoder_sys_t *p_sys = p_dec->p_sys;
00256 ogg_packet oggpacket;
00257 uint8_t *p_extra;
00258 int i_extra;
00259
00260 if( !p_dec->fmt_in.i_extra ) return VLC_EGENERIC;
00261
00262 oggpacket.granulepos = -1;
00263 oggpacket.b_o_s = 1;
00264 oggpacket.e_o_s = 0;
00265 oggpacket.packetno = 0;
00266 p_extra = p_dec->fmt_in.p_extra;
00267 i_extra = p_dec->fmt_in.i_extra;
00268
00269
00270 oggpacket.bytes = *(p_extra++) << 8;
00271 oggpacket.bytes |= (*(p_extra++) & 0xFF);
00272 oggpacket.packet = p_extra;
00273 p_extra += oggpacket.bytes;
00274 i_extra -= (oggpacket.bytes + 2);
00275 if( i_extra < 0 )
00276 {
00277 msg_Err( p_dec, "header data corrupted");
00278 return VLC_EGENERIC;
00279 }
00280
00281
00282 if( ProcessInitialHeader( p_dec, &oggpacket ) != VLC_SUCCESS )
00283 {
00284 msg_Err( p_dec, "initial Speex header is corrupted" );
00285 return VLC_EGENERIC;
00286 }
00287
00288
00289 oggpacket.b_o_s = 0;
00290 oggpacket.bytes = *(p_extra++) << 8;
00291 oggpacket.bytes |= (*(p_extra++) & 0xFF);
00292 oggpacket.packet = p_extra;
00293 p_extra += oggpacket.bytes;
00294 i_extra -= (oggpacket.bytes + 2);
00295 if( i_extra < 0 )
00296 {
00297 msg_Err( p_dec, "header data corrupted");
00298 return VLC_EGENERIC;
00299 }
00300
00301 ParseSpeexComments( p_dec, &oggpacket );
00302
00303 if( p_sys->b_packetizer )
00304 {
00305 p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;
00306 p_dec->fmt_out.p_extra =
00307 realloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra );
00308 memcpy( p_dec->fmt_out.p_extra,
00309 p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra );
00310 }
00311
00312 return VLC_SUCCESS;
00313 }
00314
00315
00316
00317
00318 static int ProcessInitialHeader( decoder_t *p_dec, ogg_packet *p_oggpacket )
00319 {
00320 decoder_sys_t *p_sys = p_dec->p_sys;
00321
00322 void *p_state;
00323 SpeexHeader *p_header;
00324 const SpeexMode *p_mode;
00325 SpeexCallback callback;
00326
00327 p_sys->p_header = p_header =
00328 speex_packet_to_header( (char *)p_oggpacket->packet,
00329 p_oggpacket->bytes );
00330 if( !p_header )
00331 {
00332 msg_Err( p_dec, "cannot read Speex header" );
00333 return VLC_EGENERIC;
00334 }
00335 if( p_header->mode >= SPEEX_NB_MODES )
00336 {
00337 msg_Err( p_dec, "mode number %d does not (yet/any longer) exist in "
00338 "this version of libspeex.", p_header->mode );
00339 return VLC_EGENERIC;
00340 }
00341
00342 p_mode = speex_mode_list[p_header->mode];
00343
00344 if( p_header->speex_version_id > 1 )
00345 {
00346 msg_Err( p_dec, "this file was encoded with Speex bit-stream "
00347 "version %d, which I don't know how to decode.",
00348 p_header->speex_version_id );
00349 return VLC_EGENERIC;
00350 }
00351
00352 if( p_mode->bitstream_version < p_header->mode_bitstream_version )
00353 {
00354 msg_Err( p_dec, "file encoded with a newer version of Speex." );
00355 return VLC_EGENERIC;
00356 }
00357 if( p_mode->bitstream_version > p_header->mode_bitstream_version )
00358 {
00359 msg_Err( p_dec, "file encoded with an older version of Speex." );
00360 return VLC_EGENERIC;
00361 }
00362
00363 msg_Dbg( p_dec, "Speex %d Hz audio using %s mode %s%s",
00364 p_header->rate, p_mode->modeName,
00365 ( p_header->nb_channels == 1 ) ? " (mono" : " (stereo",
00366 p_header->vbr ? ", VBR)" : ")" );
00367
00368
00369 speex_bits_init( &p_sys->bits );
00370 p_sys->p_state = p_state = speex_decoder_init( p_mode );
00371 if( !p_state )
00372 {
00373 msg_Err( p_dec, "decoder initialization failed" );
00374 return VLC_EGENERIC;
00375 }
00376
00377 if( p_header->nb_channels == 2 )
00378 {
00379 SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT;
00380 p_sys->stereo = stereo;
00381 callback.callback_id = SPEEX_INBAND_STEREO;
00382 callback.func = speex_std_stereo_request_handler;
00383 callback.data = &p_sys->stereo;
00384 speex_decoder_ctl( p_state, SPEEX_SET_HANDLER, &callback );
00385 }
00386
00387
00388 p_dec->fmt_out.audio.i_physical_channels =
00389 p_dec->fmt_out.audio.i_original_channels =
00390 pi_channels_maps[p_header->nb_channels];
00391 p_dec->fmt_out.audio.i_channels = p_header->nb_channels;
00392 p_dec->fmt_out.audio.i_rate = p_header->rate;
00393
00394 aout_DateInit( &p_sys->end_date, p_header->rate );
00395
00396 return VLC_SUCCESS;
00397 }
00398
00399
00400
00401
00402 static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
00403 block_t **pp_block )
00404 {
00405 decoder_sys_t *p_sys = p_dec->p_sys;
00406 block_t *p_block = *pp_block;
00407
00408
00409 if( p_block && p_block->i_pts > 0 &&
00410 p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
00411 {
00412 aout_DateSet( &p_sys->end_date, p_block->i_pts );
00413 }
00414
00415 if( !aout_DateGet( &p_sys->end_date ) )
00416 {
00417
00418 if( p_block ) block_Release( p_block );
00419 return NULL;
00420 }
00421
00422 *pp_block = NULL;
00423
00424 if( p_sys->b_packetizer )
00425 {
00426 return SendPacket( p_dec, p_oggpacket, p_block );
00427 }
00428 else
00429 {
00430 aout_buffer_t *p_aout_buffer;
00431
00432 if( p_sys->i_headers >= p_sys->p_header->extra_headers + 2 )
00433 p_aout_buffer = DecodePacket( p_dec, p_oggpacket );
00434 else
00435 p_aout_buffer = NULL;
00436
00437 if( p_block ) block_Release( p_block );
00438 return p_aout_buffer;
00439 }
00440 }
00441
00442
00443
00444
00445 static aout_buffer_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
00446 {
00447 decoder_sys_t *p_sys = p_dec->p_sys;
00448
00449 if( p_oggpacket->bytes )
00450 {
00451
00452 speex_bits_read_from( &p_sys->bits, (char *)p_oggpacket->packet,
00453 p_oggpacket->bytes );
00454 p_sys->i_frame_in_packet = 0;
00455 }
00456
00457
00458 if( p_sys->i_frame_in_packet < p_sys->p_header->frames_per_packet )
00459 {
00460 aout_buffer_t *p_aout_buffer;
00461 int i_ret;
00462
00463 p_aout_buffer =
00464 p_dec->pf_aout_buffer_new( p_dec, p_sys->p_header->frame_size );
00465 if( !p_aout_buffer )
00466 {
00467 return NULL;
00468 }
00469
00470 i_ret = speex_decode_int( p_sys->p_state, &p_sys->bits,
00471 (int16_t *)p_aout_buffer->p_buffer );
00472 if( i_ret == -1 )
00473 {
00474
00475 return NULL;
00476 }
00477
00478 if( i_ret== -2 )
00479 {
00480 msg_Warn( p_dec, "decoding error: corrupted stream?" );
00481 return NULL;
00482 }
00483
00484 if( speex_bits_remaining( &p_sys->bits ) < 0 )
00485 {
00486 msg_Warn( p_dec, "decoding overflow: corrupted stream?" );
00487 }
00488
00489 if( p_sys->p_header->nb_channels == 2 )
00490 speex_decode_stereo_int( (int16_t *)p_aout_buffer->p_buffer,
00491 p_sys->p_header->frame_size,
00492 &p_sys->stereo );
00493
00494
00495 p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
00496 p_aout_buffer->end_date =
00497 aout_DateIncrement( &p_sys->end_date, p_sys->p_header->frame_size);
00498
00499 p_sys->i_frame_in_packet++;
00500
00501 return p_aout_buffer;
00502 }
00503 else
00504 {
00505 return NULL;
00506 }
00507 }
00508
00509
00510
00511
00512 static block_t *SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
00513 block_t *p_block )
00514 {
00515 decoder_sys_t *p_sys = p_dec->p_sys;
00516
00517
00518 p_block->i_dts = p_block->i_pts = aout_DateGet( &p_sys->end_date );
00519
00520 if( p_sys->i_headers >= p_sys->p_header->extra_headers + 2 )
00521 p_block->i_length =
00522 aout_DateIncrement( &p_sys->end_date,
00523 p_sys->p_header->frame_size ) -
00524 p_block->i_pts;
00525 else
00526 p_block->i_length = 0;
00527
00528 return p_block;
00529 }
00530
00531
00532
00533
00534 #define readint(buf, base) (((buf[base+3]<<24)&0xff000000)| \
00535 ((buf[base+2]<<16)&0xff0000)| \
00536 ((buf[base+1]<<8)&0xff00)| \
00537 (buf[base]&0xff))
00538
00539 static void ParseSpeexComments( decoder_t *p_dec, ogg_packet *p_oggpacket )
00540 {
00541 input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;
00542 decoder_sys_t *p_sys = p_dec->p_sys;
00543
00544 char *p_buf = (char *)p_oggpacket->packet;
00545 const SpeexMode *p_mode;
00546 int i_len;
00547
00548 if( p_input->i_object_type != VLC_OBJECT_INPUT ) return;
00549
00550 p_mode = speex_mode_list[p_sys->p_header->mode];
00551
00552 input_Control( p_input, INPUT_ADD_INFO, _("Speex comment"), _("Mode"),
00553 "%s%s", p_mode->modeName,
00554 p_sys->p_header->vbr ? " VBR" : "" );
00555
00556 if( p_oggpacket->bytes < 8 )
00557 {
00558 msg_Warn( p_dec, "invalid/corrupted comments" );
00559 return;
00560 }
00561
00562 i_len = readint( p_buf, 0 ); p_buf += 4;
00563 if( i_len > p_oggpacket->bytes - 4 )
00564 {
00565 msg_Warn( p_dec, "invalid/corrupted comments" );
00566 return;
00567 }
00568
00569 input_Control( p_input, INPUT_ADD_INFO, _("Speex comment"), p_buf, "" );
00570
00571
00572 }
00573
00574
00575
00576
00577 static void CloseDecoder( vlc_object_t *p_this )
00578 {
00579 decoder_t * p_dec = (decoder_t *)p_this;
00580 decoder_sys_t *p_sys = p_dec->p_sys;
00581
00582 if( p_sys->p_state )
00583 {
00584 speex_decoder_destroy( p_sys->p_state );
00585 speex_bits_destroy( &p_sys->bits );
00586 }
00587
00588 if( p_sys->p_header ) free( p_sys->p_header );
00589 free( p_sys );
00590 }
00591
00592
00593
00594
00595 #define MAX_FRAME_SIZE 2000
00596 #define MAX_FRAME_BYTES 2000
00597
00598 struct encoder_sys_t
00599 {
00600
00601
00602
00603 char *p_buffer;
00604 char p_buffer_out[MAX_FRAME_BYTES];
00605
00606
00607
00608
00609 SpeexBits bits;
00610 SpeexHeader header;
00611 SpeexStereoState stereo;
00612 void *p_state;
00613
00614 int i_frames_per_packet;
00615 int i_frames_in_packet;
00616
00617 int i_frame_length;
00618 int i_samples_delay;
00619 int i_frame_size;
00620
00621
00622
00623
00624 mtime_t i_pts;
00625 };
00626
00627
00628
00629
00630 static int OpenEncoder( vlc_object_t *p_this )
00631 {
00632 encoder_t *p_enc = (encoder_t *)p_this;
00633 encoder_sys_t *p_sys;
00634 const SpeexMode *p_speex_mode = &speex_nb_mode;
00635 int i_quality, i;
00636 char *pp_header[2];
00637 int pi_header[2];
00638 uint8_t *p_extra;
00639
00640 if( p_enc->fmt_out.i_codec != VLC_FOURCC('s','p','x',' ') &&
00641 !p_enc->b_force )
00642 {
00643 return VLC_EGENERIC;
00644 }
00645
00646
00647 if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
00648 {
00649 msg_Err( p_enc, "out of memory" );
00650 return VLC_EGENERIC;
00651 }
00652 p_enc->p_sys = p_sys;
00653 p_enc->pf_encode_audio = Encode;
00654 p_enc->fmt_in.i_codec = AOUT_FMT_S16_NE;
00655 p_enc->fmt_out.i_codec = VLC_FOURCC('s','p','x',' ');
00656
00657 speex_init_header( &p_sys->header, p_enc->fmt_in.audio.i_rate,
00658 1, p_speex_mode );
00659
00660 p_sys->header.frames_per_packet = 1;
00661 p_sys->header.vbr = 1;
00662 p_sys->header.nb_channels = p_enc->fmt_in.audio.i_channels;
00663
00664
00665 p_sys->p_state = speex_encoder_init( p_speex_mode );
00666
00667
00668 i_quality = 8;
00669 speex_encoder_ctl( p_sys->p_state, SPEEX_SET_QUALITY, &i_quality );
00670
00671
00672 speex_bits_init( &p_sys->bits );
00673
00674 p_sys->i_frames_in_packet = 0;
00675 p_sys->i_samples_delay = 0;
00676 p_sys->i_pts = 0;
00677
00678 speex_encoder_ctl( p_sys->p_state, SPEEX_GET_FRAME_SIZE,
00679 &p_sys->i_frame_length );
00680
00681 p_sys->i_frame_size = p_sys->i_frame_length *
00682 sizeof(int16_t) * p_enc->fmt_in.audio.i_channels;
00683 p_sys->p_buffer = malloc( p_sys->i_frame_size );
00684
00685
00686 pp_header[0] = speex_header_to_packet( &p_sys->header, &pi_header[0] );
00687 pp_header[1] = "ENCODER=VLC media player";
00688 pi_header[1] = sizeof("ENCODER=VLC media player");
00689
00690 p_enc->fmt_out.i_extra = 3 * 2 + pi_header[0] + pi_header[1];
00691 p_extra = p_enc->fmt_out.p_extra = malloc( p_enc->fmt_out.i_extra );
00692 for( i = 0; i < 2; i++ )
00693 {
00694 *(p_extra++) = pi_header[i] >> 8;
00695 *(p_extra++) = pi_header[i] & 0xFF;
00696 memcpy( p_extra, pp_header[i], pi_header[i] );
00697 p_extra += pi_header[i];
00698 }
00699
00700 msg_Dbg( p_enc, "encoding: frame size:%d, channels:%d, samplerate:%d",
00701 p_sys->i_frame_size, p_enc->fmt_in.audio.i_channels,
00702 p_enc->fmt_in.audio.i_rate );
00703
00704 return VLC_SUCCESS;
00705 }
00706
00707
00708
00709
00710
00711
00712 static block_t *Encode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
00713 {
00714 encoder_sys_t *p_sys = p_enc->p_sys;
00715 block_t *p_block, *p_chain = NULL;
00716
00717 unsigned char *p_buffer = p_aout_buf->p_buffer;
00718 int i_samples = p_aout_buf->i_nb_samples;
00719 int i_samples_delay = p_sys->i_samples_delay;
00720
00721 p_sys->i_pts = p_aout_buf->start_date -
00722 (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay /
00723 (mtime_t)p_enc->fmt_in.audio.i_rate;
00724
00725 p_sys->i_samples_delay += i_samples;
00726
00727 while( p_sys->i_samples_delay >= p_sys->i_frame_length )
00728 {
00729 int16_t *p_samples;
00730 int i_out;
00731
00732 if( i_samples_delay )
00733 {
00734
00735 int i_delay_size = i_samples_delay * 2 *
00736 p_enc->fmt_in.audio.i_channels;
00737 int i_size = p_sys->i_frame_size - i_delay_size;
00738
00739 p_samples = (int16_t *)p_sys->p_buffer;
00740 memcpy( p_sys->p_buffer + i_delay_size, p_buffer, i_size );
00741 p_buffer -= i_delay_size;
00742 i_samples += i_samples_delay;
00743 i_samples_delay = 0;
00744 }
00745 else
00746 {
00747 p_samples = (int16_t *)p_buffer;
00748 }
00749
00750
00751 if( p_enc->fmt_in.audio.i_channels == 2 )
00752 speex_encode_stereo_int( p_samples, p_sys->i_frame_length,
00753 &p_sys->bits );
00754
00755 #if 0
00756 if( p_sys->preprocess )
00757 speex_preprocess( p_sys->preprocess, p_samples, NULL );
00758 #endif
00759
00760 speex_encode_int( p_sys->p_state, p_samples, &p_sys->bits );
00761
00762 p_buffer += p_sys->i_frame_size;
00763 p_sys->i_samples_delay -= p_sys->i_frame_length;
00764 i_samples -= p_sys->i_frame_length;
00765
00766 p_sys->i_frames_in_packet++;
00767
00768 if( p_sys->i_frames_in_packet < p_sys->header.frames_per_packet )
00769 continue;
00770
00771 p_sys->i_frames_in_packet = 0;
00772
00773 speex_bits_insert_terminator( &p_sys->bits );
00774 i_out = speex_bits_write( &p_sys->bits, p_sys->p_buffer_out,
00775 MAX_FRAME_BYTES );
00776 speex_bits_reset( &p_sys->bits );
00777
00778 p_block = block_New( p_enc, i_out );
00779 memcpy( p_block->p_buffer, p_sys->p_buffer_out, i_out );
00780
00781 p_block->i_length = (mtime_t)1000000 *
00782 (mtime_t)p_sys->i_frame_length * p_sys->header.frames_per_packet /
00783 (mtime_t)p_enc->fmt_in.audio.i_rate;
00784
00785 p_block->i_dts = p_block->i_pts = p_sys->i_pts;
00786
00787
00788 p_sys->i_pts += p_block->i_length;
00789 block_ChainAppend( &p_chain, p_block );
00790
00791 }
00792
00793
00794 if( i_samples )
00795 {
00796 memcpy( p_sys->p_buffer + i_samples_delay * 2 *
00797 p_enc->fmt_in.audio.i_channels, p_buffer,
00798 i_samples * 2 * p_enc->fmt_in.audio.i_channels );
00799 }
00800
00801 return p_chain;
00802 }
00803
00804
00805
00806
00807 static void CloseEncoder( vlc_object_t *p_this )
00808 {
00809 encoder_t *p_enc = (encoder_t *)p_this;
00810 encoder_sys_t *p_sys = p_enc->p_sys;
00811
00812 speex_encoder_destroy( p_sys->p_state );
00813 speex_bits_destroy( &p_sys->bits );
00814
00815 if( p_sys->p_buffer ) free( p_sys->p_buffer );
00816 free( p_sys );
00817 }