00001 #include "funcprotos.h"
00002 #include "quicktime.h"
00003 #include "qtvorbis.h"
00004 #include <string.h>
00005 #include "vorbis/vorbisenc.h"
00006
00007
00008 #define OUTPUT_ALLOCATION 0x100000
00009 #define CLAMP(x, y, z) ((x) = ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x))))
00010
00011 typedef struct
00012 {
00013 int max_bitrate;
00014 int nominal_bitrate;
00015 int min_bitrate;
00016 int use_vbr;
00017 int encode_initialized;
00018 ogg_stream_state enc_os;
00019 ogg_page enc_og;
00020 ogg_packet enc_op;
00021 vorbis_info enc_vi;
00022 vorbis_comment enc_vc;
00023 vorbis_dsp_state enc_vd;
00024 vorbis_block enc_vb;
00025
00026 int encoded_samples;
00027
00028 int64_t encoded_bytes;
00029
00030
00031
00032 int next_chunk_size;
00033
00034
00035
00036 ogg_sync_state dec_oy;
00037 ogg_stream_state dec_os;
00038
00039 ogg_page dec_og;
00040 ogg_packet dec_op;
00041
00042 vorbis_info dec_vi;
00043
00044 vorbis_comment dec_vc;
00045 vorbis_dsp_state dec_vd;
00046 vorbis_block dec_vb;
00047
00048 unsigned int dec_current_serialno;
00049 int decode_initialized;
00050 float **output;
00051
00052
00053 int64_t output_position;
00054
00055 long output_end;
00056
00057 long output_size;
00058
00059 long output_allocated;
00060
00061 int64_t chunk;
00062
00063 int chunk_samples;
00064 } quicktime_vorbis_codec_t;
00065
00066
00067
00068
00069 static int delete_codec(quicktime_audio_map_t *atrack)
00070 {
00071 quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
00072 int i;
00073
00074 if(codec->encode_initialized)
00075 {
00076 ogg_stream_clear(&codec->enc_os);
00077 vorbis_block_clear(&codec->enc_vb);
00078 vorbis_dsp_clear(&codec->enc_vd);
00079 vorbis_comment_clear(&codec->enc_vc);
00080 vorbis_info_clear(&codec->enc_vi);
00081 }
00082
00083 if(codec->decode_initialized)
00084 {
00085 if(codec->output)
00086 {
00087 for(i = 0; i < atrack->channels; i++)
00088 free(codec->output[i]);
00089
00090 free(codec->output);
00091 }
00092
00093 ogg_stream_clear(&codec->dec_os);
00094 vorbis_block_clear(&codec->dec_vb);
00095 vorbis_dsp_clear(&codec->dec_vd);
00096 vorbis_comment_clear(&codec->dec_vc);
00097 vorbis_info_clear(&codec->dec_vi);
00098 }
00099
00100 free(codec);
00101 return 0;
00102 }
00103
00104
00105
00106
00107
00108
00109
00110 #define BUFFER_FRAGMENT 4096
00111
00112
00113
00114
00115 #define SEGMENT_OFFSET 0x1a
00116 #define LACE_OFFSET 0x1b
00117 static int chunk_len(quicktime_t *file, int64_t offset, int64_t next_chunk)
00118 {
00119 int result = 0;
00120 unsigned char buffer[BUFFER_FRAGMENT];
00121 int accum = 0;
00122 int segment_count = 0;
00123 int segment_size = 0;
00124 int lace_size = 0;
00125 int page_size = 0;
00126 int i, j;
00127
00128 while(offset < next_chunk)
00129 {
00130 quicktime_set_position(file, offset);
00131 result = !quicktime_read_data(file, buffer, BUFFER_FRAGMENT);
00132
00133 if(result)
00134 {
00135 return accum;
00136 }
00137
00138 if(memcmp(buffer, "OggS", 4))
00139 {
00140 return accum;
00141 }
00142 else
00143 {
00144 }
00145
00146
00147 segment_count = buffer[SEGMENT_OFFSET];
00148
00149
00150 i = LACE_OFFSET;
00151 page_size = 0;
00152 while(segment_count > 0)
00153 {
00154 page_size += buffer[i++];
00155 segment_count--;
00156 }
00157 accum += i + page_size;
00158 offset += i + page_size;
00159 }
00160
00161
00162 return accum;
00163 }
00164
00165
00166
00167 #define READ_CHUNK(chunk) \
00168 { \
00169 int64_t offset1 = quicktime_chunk_to_offset(file, trak, (chunk)); \
00170 int64_t offset2 = quicktime_chunk_to_offset(file, trak, (chunk) + 1); \
00171 int size = 0; \
00172 if(offset2 == offset1) \
00173 result = 1; \
00174 else \
00175 { \
00176 size = chunk_len(file, offset1, \
00177 offset2 > offset1 ? offset2 : offset1 + 0xfffff); \
00178 \
00179 buffer = ogg_sync_buffer(&codec->dec_oy, size); \
00180 quicktime_set_position(file, offset1); \
00181 result = !quicktime_read_data(file, buffer, size); \
00182 ogg_sync_wrote(&codec->dec_oy, size); \
00183 } \
00184 \
00185 \
00186 \
00187 \
00188 \
00189 }
00190
00191
00192
00193
00194 static int decode(quicktime_t *file,
00195 int16_t *output_i,
00196 float *output_f,
00197 long samples,
00198 int track,
00199 int channel)
00200 {
00201 int result = 0;
00202 int bytes;
00203 int i, j;
00204 quicktime_audio_map_t *track_map = &(file->atracks[track]);
00205 quicktime_trak_t *trak = track_map->track;
00206 quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
00207 long current_position = track_map->current_position;
00208 long end_position = current_position + samples;
00209 unsigned char *buffer;
00210
00211 int eos = 0;
00212
00213 int eof = 0;
00214 float *pcm;
00215 int have_chunk = 0;
00216
00217
00218 if(samples > OUTPUT_ALLOCATION)
00219 printf("vorbis.c decode: can't read more than %p samples at a time.\n", OUTPUT_ALLOCATION);
00220
00221
00222
00223 if(output_i) bzero(output_i, sizeof(int16_t) * samples);
00224 if(output_f) bzero(output_f, sizeof(float) * samples);
00225
00226
00227
00228
00229
00230
00231
00232
00233 if(current_position < codec->output_position - codec->output_size ||
00234 current_position > codec->output_position ||
00235 !codec->decode_initialized)
00236 {
00237
00238 quicktime_chunk_of_sample(&codec->output_position,
00239 &codec->chunk,
00240 trak,
00241 current_position);
00242
00243
00244 codec->output_size = 0;
00245 codec->output_end = 0;
00246 codec->chunk_samples = 0;
00247
00248
00249
00250
00251
00252 if(!codec->decode_initialized)
00253 {
00254 int init_chunk = 1;
00255 codec->decode_initialized = 1;
00256
00257 codec->output = malloc(sizeof(float*) * track_map->channels);
00258 for(i = 0; i < track_map->channels; i++)
00259 {
00260 codec->output[i] = malloc(sizeof(float) * OUTPUT_ALLOCATION);
00261 }
00262
00263 codec->output_allocated = OUTPUT_ALLOCATION;
00264
00265 ogg_sync_init(&codec->dec_oy);
00266
00267
00268
00269
00270 READ_CHUNK(init_chunk);
00271 init_chunk++;
00272
00273 if(ogg_sync_pageout(&codec->dec_oy, &codec->dec_og)!=1)
00274 {
00275 fprintf(stderr, "decode: ogg_sync_pageout: Must not be Vorbis data\n");
00276 return 1;
00277 }
00278
00279
00280 ogg_stream_init(&codec->dec_os, ogg_page_serialno(&codec->dec_og));
00281 vorbis_info_init(&codec->dec_vi);
00282 vorbis_comment_init(&codec->dec_vc);
00283
00284 if(ogg_stream_pagein(&codec->dec_os, &codec->dec_og) < 0)
00285 {
00286 fprintf(stderr,"decode: ogg_stream_pagein: stream version mismatch perhaps.\n");
00287 return 1;
00288 }
00289
00290 if(ogg_stream_packetout(&codec->dec_os, &codec->dec_op) != 1)
00291 {
00292 fprintf(stderr, "decode: ogg_stream_packetout: Must not be Vorbis data\n");
00293 return 1;
00294 }
00295
00296 if(vorbis_synthesis_headerin(&codec->dec_vi, &codec->dec_vc, &codec->dec_op) < 0)
00297 {
00298 fprintf(stderr, "decode: vorbis_synthesis_headerin: not a vorbis header\n");
00299 return 1;
00300 }
00301
00302
00303 i = 0;
00304 while(i < 2)
00305 {
00306 while(i < 2)
00307 {
00308 result = ogg_sync_pageout(&codec->dec_oy, &codec->dec_og);
00309 if(result == 0) break;
00310
00311 if(result == 1)
00312 {
00313 ogg_stream_pagein(&codec->dec_os, &codec->dec_og);
00314
00315 while(i < 2)
00316 {
00317 result = ogg_stream_packetout(&codec->dec_os, &codec->dec_op);
00318
00319 if(result == 0) break;
00320
00321 if(result < 0)
00322 {
00323 fprintf(stderr, "decode: ogg_stream_packetout: corrupt secondary header\n");
00324 return 1;
00325 }
00326
00327 vorbis_synthesis_headerin(&codec->dec_vi, &codec->dec_vc, &codec->dec_op);
00328 i++;
00329
00330
00331
00332
00333 }
00334 }
00335 }
00336
00337 if(i < 2)
00338 {
00339 READ_CHUNK(init_chunk);
00340 init_chunk++;
00341 }
00342
00343
00344 }
00345
00346 vorbis_synthesis_init(&codec->dec_vd, &codec->dec_vi);
00347 vorbis_block_init(&codec->dec_vd, &codec->dec_vb);
00348
00349
00350 if(codec->chunk == init_chunk - 1)
00351 {
00352 have_chunk = 1;
00353 codec->chunk++;
00354 }
00355 }
00356
00357
00358
00359
00360
00361 if(!have_chunk)
00362 {
00363
00364
00365
00366 ogg_stream_clear(&codec->dec_os);
00367 vorbis_dsp_clear(&codec->dec_vd);
00368 vorbis_block_clear(&codec->dec_vb);
00369 ogg_sync_reset(&codec->dec_oy);
00370
00371 ogg_stream_init(&codec->dec_os, ogg_page_serialno(&codec->dec_og));
00372 ogg_sync_init(&codec->dec_oy);
00373 vorbis_synthesis_init(&codec->dec_vd, &codec->dec_vi);
00374 vorbis_block_init(&codec->dec_vd, &codec->dec_vb);
00375
00376
00377 READ_CHUNK(codec->chunk);
00378 codec->chunk++;
00379 have_chunk = 1;
00380 }
00381 }
00382
00383
00384
00385 have_chunk = 1;
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398 result = 0;
00399 while(codec->output_position < end_position)
00400 {
00401
00402
00403
00404 if(!have_chunk)
00405 {
00406 codec->chunk_samples = 0;
00407
00408 READ_CHUNK(codec->chunk);
00409 if(result) break;
00410 codec->chunk++;
00411 }
00412
00413 eos = 0;
00414 while(!eos)
00415 {
00416 result = ogg_sync_pageout(&codec->dec_oy, &codec->dec_og);
00417
00418
00419
00420
00421
00422
00423
00424
00425 if(result == 0)
00426 {
00427
00428 eos = 1;
00429 }
00430 else
00431
00432
00433
00434 if(result < 0)
00435 {
00436
00437 ;
00438 }
00439 else
00440 {
00441 ogg_stream_pagein(&codec->dec_os, &codec->dec_og);
00442
00443
00444
00445 while(!eos)
00446 {
00447
00448 result = ogg_stream_packetout(&codec->dec_os, &codec->dec_op);
00449
00450
00451 if(result == 0)
00452 {
00453
00454
00455 eos = 1;
00456 }
00457 else
00458
00459 if(result < 0)
00460 {
00461
00462 }
00463 else
00464 {
00465 float **pcm;
00466
00467
00468
00469
00470
00471
00472
00473 if(vorbis_synthesis(&codec->dec_vb, &codec->dec_op) == 0)
00474 {
00475 vorbis_synthesis_blockin(&codec->dec_vd,
00476 &codec->dec_vb);
00477 }
00478
00479
00480 while((result = vorbis_synthesis_pcmout(&codec->dec_vd, &pcm)) > 0)
00481 {
00482
00483 for(i = 0; i < track_map->channels; i++)
00484 {
00485 float *output_channel = codec->output[i];
00486 float *input_channel = pcm[i];
00487 int k = codec->output_end;
00488
00489 for(j = 0; j < result; j++)
00490 {
00491 output_channel[k++] = input_channel[j];
00492 if(k >= codec->output_allocated)
00493 k = 0;
00494 }
00495
00496 if(i == track_map->channels - 1)
00497 codec->output_end = k;
00498 }
00499
00500
00501 codec->output_position += result;
00502 codec->output_size += result;
00503 codec->chunk_samples += result;
00504 if(codec->output_size > codec->output_allocated)
00505 codec->output_size = codec->output_allocated;
00506 vorbis_synthesis_read(&codec->dec_vd, result);
00507 }
00508 }
00509
00510 }
00511
00512
00513 eos = 0;
00514 }
00515 }
00516
00517
00518
00519 if(eos)
00520 {
00521
00522 have_chunk = 0;
00523 }
00524 }
00525
00526
00527
00528 while(codec->output_position < end_position)
00529 {
00530 for(i = 0; i < track_map->channels; i++)
00531 codec->output[i][codec->output_end] = 0;
00532
00533 codec->output_end++;
00534 if(codec->output_end >= codec->output_allocated)
00535 codec->output_end = 0;
00536 codec->output_position++;
00537 }
00538
00539
00540
00541
00542
00543
00544 current_position = track_map->current_position;
00545 i = codec->output_end - (codec->output_position - current_position);
00546 j = 0;
00547 while(i < 0) i += codec->output_allocated;
00548 pcm = codec->output[channel];
00549
00550 if(output_i)
00551 {
00552 for( ; j < samples; j++)
00553 {
00554 int sample = pcm[i] * 32767;
00555 CLAMP(sample, -32768, 32767);
00556 output_i[j] = sample;
00557
00558 i++;
00559 if(i >= codec->output_allocated) i = 0;
00560 }
00561 }
00562 else
00563 if(output_f)
00564 {
00565 for( ; j < samples; j++)
00566 {
00567 output_f[j] = pcm[i];
00568 i++;
00569 if(i >= codec->output_allocated) i = 0;
00570 }
00571 }
00572
00573
00574 return 0;
00575 }
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596 #define FLUSH_OGG1 \
00597 while(1) \
00598 { \
00599 int eos = !ogg_stream_flush(&codec->enc_os, &codec->enc_og); \
00600 if(eos) break; \
00601 \
00602 if(!chunk_started) \
00603 { \
00604 chunk_started = 1; \
00605 quicktime_write_chunk_header(file, trak, &chunk_atom); \
00606 } \
00607 \
00608 result = !quicktime_write_data(file, codec->enc_og.header, codec->enc_og.header_len); \
00609 size += codec->enc_og.header_len; \
00610 \
00611 if(!result) \
00612 { \
00613 result = !quicktime_write_data(file, codec->enc_og.body, codec->enc_og.body_len); \
00614 size += codec->enc_og.body_len; \
00615 } \
00616 \
00617 \
00618 if(!result) break; \
00619 }
00620
00621
00622
00623 #define FLUSH_OGG2 \
00624 while(vorbis_analysis_blockout(&codec->enc_vd, &codec->enc_vb) == 1) \
00625 { \
00626 vorbis_analysis(&codec->enc_vb, &codec->enc_op); \
00627 vorbis_bitrate_addblock(&codec->enc_vb); \
00628 while(vorbis_bitrate_flushpacket(&codec->enc_vd, &codec->enc_op)) \
00629 { \
00630 ogg_stream_packetin(&codec->enc_os, &codec->enc_op); \
00631 \
00632 while(!result) \
00633 { \
00634 if(!ogg_stream_pageout(&codec->enc_os, &codec->enc_og)) break; \
00635 \
00636 \
00637 if(!chunk_started) \
00638 { \
00639 chunk_started = 1; \
00640 quicktime_write_chunk_header(file, trak, &chunk_atom); \
00641 } \
00642 result = !quicktime_write_data(file, codec->enc_og.header, codec->enc_og.header_len); \
00643 size += codec->enc_og.header_len; \
00644 \
00645 if(!result) \
00646 { \
00647 result = !quicktime_write_data(file, codec->enc_og.body, codec->enc_og.body_len); \
00648 size += codec->enc_og.body_len; \
00649 } \
00650 \
00651 if(ogg_page_eos(&codec->enc_og)) break; \
00652 } \
00653 } \
00654 }
00655
00656
00657 static int encode(quicktime_t *file,
00658 int16_t **input_i,
00659 float **input_f,
00660 int track,
00661 long samples)
00662 {
00663 int result = 0;
00664 int64_t offset = quicktime_position(file);
00665 quicktime_audio_map_t *track_map = &(file->atracks[track]);
00666 quicktime_trak_t *trak = track_map->track;
00667 quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
00668 int samplerate = trak->mdia.minf.stbl.stsd.table[0].sample_rate;
00669 float **output;
00670 int size = 0;
00671 int chunk_started = 0;
00672 quicktime_atom_t chunk_atom;
00673
00674
00675 if(samplerate < 32000)
00676 {
00677 printf("encode: sample rate %d not supported.\n", samplerate);
00678 return 1;
00679 }
00680
00681
00682
00683
00684
00685 if(!codec->encode_initialized)
00686 {
00687 ogg_packet header;
00688 ogg_packet header_comm;
00689 ogg_packet header_code;
00690
00691
00692 codec->encode_initialized = 1;
00693 if(file->use_avi)
00694 trak->mdia.minf.stbl.stsd.table[0].sample_size = 0;
00695 vorbis_info_init(&codec->enc_vi);
00696
00697 if(codec->use_vbr)
00698 {
00699 result = vorbis_encode_setup_managed(&codec->enc_vi,
00700 track_map->channels,
00701 samplerate,
00702 codec->max_bitrate,
00703 codec->nominal_bitrate,
00704 codec->min_bitrate);
00705 result |= vorbis_encode_ctl(&codec->enc_vi, OV_ECTL_RATEMANAGE_AVG, NULL);
00706 result |= vorbis_encode_setup_init(&codec->enc_vi);
00707 }
00708 else
00709 {
00710 vorbis_encode_init(&codec->enc_vi,
00711 track_map->channels,
00712 samplerate,
00713 codec->max_bitrate,
00714 codec->nominal_bitrate,
00715 codec->min_bitrate);
00716 }
00717
00718
00719 vorbis_comment_init(&codec->enc_vc);
00720 vorbis_analysis_init(&codec->enc_vd, &codec->enc_vi);
00721 vorbis_block_init(&codec->enc_vd, &codec->enc_vb);
00722 srand(time(NULL));
00723 ogg_stream_init(&codec->enc_os, rand());
00724
00725
00726 vorbis_analysis_headerout(&codec->enc_vd,
00727 &codec->enc_vc,
00728 &header,
00729 &header_comm,
00730 &header_code);
00731
00732 ogg_stream_packetin(&codec->enc_os, &header);
00733 ogg_stream_packetin(&codec->enc_os, &header_comm);
00734 ogg_stream_packetin(&codec->enc_os, &header_code);
00735
00736 FLUSH_OGG1
00737 }
00738
00739 output = vorbis_analysis_buffer(&codec->enc_vd, samples);
00740
00741 if(input_i)
00742 {
00743 int i, j;
00744 for(i = 0; i < track_map->channels; i++)
00745 {
00746 for(j = 0; j < samples; j++)
00747 {
00748 output[i][j] = (float)input_i[i][j] / (float)32768;
00749 }
00750 }
00751 }
00752 else
00753 if(input_f)
00754 {
00755 int i;
00756 for(i = 0; i < track_map->channels; i++)
00757 {
00758 memcpy(output[i], input_f[i], sizeof(float) * samples);
00759 }
00760 }
00761
00762 vorbis_analysis_wrote(&codec->enc_vd, samples);
00763
00764 FLUSH_OGG2
00765
00766 codec->next_chunk_size += samples;
00767
00768
00769 if(chunk_started)
00770 {
00771 int new_encoded_samples = codec->enc_vd.granulepos;
00772
00773 if(!codec->use_vbr)
00774 {
00775 codec->encoded_bytes += quicktime_position(file) - offset;
00776 new_encoded_samples = codec->encoded_bytes *
00777 (int64_t)8 *
00778 (int64_t)samplerate /
00779 (int64_t)codec->nominal_bitrate;
00780 }
00781 quicktime_write_chunk_footer(file,
00782 trak,
00783 track_map->current_chunk,
00784 &chunk_atom,
00785 new_encoded_samples - codec->encoded_samples);
00786 track_map->current_chunk++;
00787 codec->next_chunk_size = 0;
00788 codec->encoded_samples = new_encoded_samples;
00789 }
00790
00791 return result;
00792 }
00793
00794
00795
00796
00797 static int set_parameter(quicktime_t *file,
00798 int track,
00799 char *key,
00800 void *value)
00801 {
00802 quicktime_audio_map_t *atrack = &(file->atracks[track]);
00803 quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
00804
00805
00806 if(!strcasecmp(key, "vorbis_vbr"))
00807 codec->use_vbr = *(int*)value;
00808 else
00809 if(!strcasecmp(key, "vorbis_bitrate"))
00810 codec->nominal_bitrate = *(int*)value;
00811 else
00812 if(!strcasecmp(key, "vorbis_max_bitrate"))
00813 codec->max_bitrate = *(int*)value;
00814 else
00815 if(!strcasecmp(key, "vorbis_min_bitrate"))
00816 codec->min_bitrate = *(int*)value;
00817 return 0;
00818 }
00819
00820
00821 static void flush(quicktime_t *file, int track)
00822 {
00823 quicktime_audio_map_t *track_map = &(file->atracks[track]);
00824 quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
00825 if(codec->encode_initialized)
00826 {
00827 int result = 0;
00828 int size = 0;
00829 int64_t offset = quicktime_position(file);
00830 long output_position = codec->enc_vd.granulepos;
00831 int chunk_started = 0;
00832 quicktime_trak_t *trak = track_map->track;
00833 int sample_rate = trak->mdia.minf.stbl.stsd.table[0].sample_rate;
00834 quicktime_atom_t chunk_atom;
00835
00836 vorbis_analysis_wrote(&codec->enc_vd,0);
00837
00838 FLUSH_OGG2
00839
00840 if(chunk_started)
00841 {
00842 int new_encoded_samples = codec->enc_vd.granulepos;
00843 if(!codec->use_vbr)
00844 {
00845 codec->encoded_bytes += quicktime_position(file) - offset;
00846 new_encoded_samples = codec->encoded_bytes *
00847 (int64_t)8 *
00848 (int64_t)sample_rate /
00849 (int64_t)codec->nominal_bitrate;
00850 }
00851 quicktime_write_chunk_footer(file,
00852 trak,
00853 track_map->current_chunk,
00854 &chunk_atom,
00855 new_encoded_samples - codec->encoded_samples);
00856 track_map->current_chunk++;
00857 codec->next_chunk_size = 0;
00858 }
00859 }
00860 }
00861
00862 void quicktime_init_codec_vorbis(quicktime_audio_map_t *atrack)
00863 {
00864 quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
00865 quicktime_vorbis_codec_t *codec;
00866
00867
00868 codec_base->priv = calloc(1, sizeof(quicktime_vorbis_codec_t));
00869 codec_base->delete_acodec = delete_codec;
00870 codec_base->decode_audio = decode;
00871 codec_base->encode_audio = encode;
00872 codec_base->set_parameter = set_parameter;
00873 codec_base->flush = flush;
00874 codec_base->fourcc = QUICKTIME_VORBIS;
00875 codec_base->title = "OGG Vorbis";
00876 codec_base->desc = "OGG Vorbis for video. (Not standardized)";
00877
00878 codec = codec_base->priv;
00879 codec->nominal_bitrate = 128000;
00880 codec->max_bitrate = -1;
00881 codec->min_bitrate = -1;
00882 }