Annotation of /trunk/indra/llaudio/vorbisencode.cpp
Parent Directory
|
Revision Log
Revision 137 - (view) (download)
| 1 : | mjm | 135 | /** |
| 2 : | * @file vorbisencode.cpp | ||
| 3 : | * @brief Vorbis encoding routine routine for Indra. | ||
| 4 : | * | ||
| 5 : | * $LicenseInfo:firstyear=2000&license=viewergpl$ | ||
| 6 : | * | ||
| 7 : | mjm | 137 | * Copyright (c) 2000-2010, Linden Research, Inc. |
| 8 : | mjm | 135 | * |
| 9 : | * Second Life Viewer Source Code | ||
| 10 : | * The source code in this file ("Source Code") is provided by Linden Lab | ||
| 11 : | * to you under the terms of the GNU General Public License, version 2.0 | ||
| 12 : | * ("GPL"), unless you have obtained a separate licensing agreement | ||
| 13 : | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
| 14 : | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
| 15 : | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
| 16 : | * | ||
| 17 : | * There are special exceptions to the terms and conditions of the GPL as | ||
| 18 : | * it is applied to this Source Code. View the full text of the exception | ||
| 19 : | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
| 20 : | * online at | ||
| 21 : | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
| 22 : | * | ||
| 23 : | * By copying, modifying or distributing this software, you acknowledge | ||
| 24 : | * that you have read and understood your obligations described above, | ||
| 25 : | * and agree to abide by those obligations. | ||
| 26 : | * | ||
| 27 : | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
| 28 : | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
| 29 : | * COMPLETENESS OR PERFORMANCE. | ||
| 30 : | * $/LicenseInfo$ | ||
| 31 : | */ | ||
| 32 : | |||
| 33 : | #include "linden_common.h" | ||
| 34 : | |||
| 35 : | #include "vorbisencode.h" | ||
| 36 : | #include "vorbis/vorbisenc.h" | ||
| 37 : | #include "llerror.h" | ||
| 38 : | #include "llrand.h" | ||
| 39 : | #include "llmath.h" | ||
| 40 : | #include "llapr.h" | ||
| 41 : | |||
| 42 : | //#if LL_DARWIN | ||
| 43 : | // MBW -- XXX -- Getting rid of SecondLifeVorbis for now -- no fmod means no name collisions. | ||
| 44 : | #if 0 | ||
| 45 : | #include "VorbisFramework.h" | ||
| 46 : | |||
| 47 : | #define vorbis_analysis mac_vorbis_analysis | ||
| 48 : | #define vorbis_analysis_headerout mac_vorbis_analysis_headerout | ||
| 49 : | #define vorbis_analysis_init mac_vorbis_analysis_init | ||
| 50 : | #define vorbis_encode_ctl mac_vorbis_encode_ctl | ||
| 51 : | #define vorbis_encode_setup_init mac_vorbis_encode_setup_init | ||
| 52 : | #define vorbis_encode_setup_managed mac_vorbis_encode_setup_managed | ||
| 53 : | |||
| 54 : | #define vorbis_info_init mac_vorbis_info_init | ||
| 55 : | #define vorbis_info_clear mac_vorbis_info_clear | ||
| 56 : | #define vorbis_comment_init mac_vorbis_comment_init | ||
| 57 : | #define vorbis_comment_clear mac_vorbis_comment_clear | ||
| 58 : | #define vorbis_block_init mac_vorbis_block_init | ||
| 59 : | #define vorbis_block_clear mac_vorbis_block_clear | ||
| 60 : | #define vorbis_dsp_clear mac_vorbis_dsp_clear | ||
| 61 : | #define vorbis_analysis_buffer mac_vorbis_analysis_buffer | ||
| 62 : | #define vorbis_analysis_wrote mac_vorbis_analysis_wrote | ||
| 63 : | #define vorbis_analysis_blockout mac_vorbis_analysis_blockout | ||
| 64 : | |||
| 65 : | #define ogg_stream_packetin mac_ogg_stream_packetin | ||
| 66 : | #define ogg_stream_init mac_ogg_stream_init | ||
| 67 : | #define ogg_stream_flush mac_ogg_stream_flush | ||
| 68 : | #define ogg_stream_pageout mac_ogg_stream_pageout | ||
| 69 : | #define ogg_page_eos mac_ogg_page_eos | ||
| 70 : | #define ogg_stream_clear mac_ogg_stream_clear | ||
| 71 : | |||
| 72 : | #endif | ||
| 73 : | |||
| 74 : | S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& error_msg) | ||
| 75 : | { | ||
| 76 : | U16 num_channels = 0; | ||
| 77 : | U32 sample_rate = 0; | ||
| 78 : | U32 bits_per_sample = 0; | ||
| 79 : | U32 physical_file_size = 0; | ||
| 80 : | U32 chunk_length = 0; | ||
| 81 : | U32 raw_data_length = 0; | ||
| 82 : | U32 bytes_per_sec = 0; | ||
| 83 : | BOOL uncompressed_pcm = FALSE; | ||
| 84 : | |||
| 85 : | unsigned char wav_header[44]; /*Flawfinder: ignore*/ | ||
| 86 : | |||
| 87 : | error_msg.clear(); | ||
| 88 : | |||
| 89 : | //******************************** | ||
| 90 : | LLAPRFile infile ; | ||
| 91 : | infile.open(in_fname,LL_APR_RB); | ||
| 92 : | //******************************** | ||
| 93 : | if (!infile.getFileHandle()) | ||
| 94 : | { | ||
| 95 : | error_msg = "CannotUploadSoundFile"; | ||
| 96 : | return(LLVORBISENC_SOURCE_OPEN_ERR); | ||
| 97 : | } | ||
| 98 : | |||
| 99 : | infile.read(wav_header, 44); | ||
| 100 : | physical_file_size = infile.seek(APR_END,0); | ||
| 101 : | |||
| 102 : | if (strncmp((char *)&(wav_header[0]),"RIFF",4)) | ||
| 103 : | { | ||
| 104 : | error_msg = "SoundFileNotRIFF"; | ||
| 105 : | return(LLVORBISENC_WAV_FORMAT_ERR); | ||
| 106 : | } | ||
| 107 : | |||
| 108 : | if (strncmp((char *)&(wav_header[8]),"WAVE",4)) | ||
| 109 : | { | ||
| 110 : | error_msg = "SoundFileNotRIFF"; | ||
| 111 : | return(LLVORBISENC_WAV_FORMAT_ERR); | ||
| 112 : | } | ||
| 113 : | |||
| 114 : | // parse the chunks | ||
| 115 : | |||
| 116 : | U32 file_pos = 12; // start at the first chunk (usually fmt but not always) | ||
| 117 : | |||
| 118 : | while ((file_pos + 8)< physical_file_size) | ||
| 119 : | { | ||
| 120 : | infile.seek(APR_SET,file_pos); | ||
| 121 : | infile.read(wav_header, 44); | ||
| 122 : | |||
| 123 : | chunk_length = ((U32) wav_header[7] << 24) | ||
| 124 : | + ((U32) wav_header[6] << 16) | ||
| 125 : | + ((U32) wav_header[5] << 8) | ||
| 126 : | + wav_header[4]; | ||
| 127 : | |||
| 128 : | // llinfos << "chunk found: '" << wav_header[0] << wav_header[1] << wav_header[2] << wav_header[3] << "'" << llendl; | ||
| 129 : | |||
| 130 : | if (!(strncmp((char *)&(wav_header[0]),"fmt ",4))) | ||
| 131 : | { | ||
| 132 : | if ((wav_header[8] == 0x01) && (wav_header[9] == 0x00)) | ||
| 133 : | { | ||
| 134 : | uncompressed_pcm = TRUE; | ||
| 135 : | } | ||
| 136 : | num_channels = ((U16) wav_header[11] << 8) + wav_header[10]; | ||
| 137 : | sample_rate = ((U32) wav_header[15] << 24) | ||
| 138 : | + ((U32) wav_header[14] << 16) | ||
| 139 : | + ((U32) wav_header[13] << 8) | ||
| 140 : | + wav_header[12]; | ||
| 141 : | bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22]; | ||
| 142 : | bytes_per_sec = ((U32) wav_header[19] << 24) | ||
| 143 : | + ((U32) wav_header[18] << 16) | ||
| 144 : | + ((U32) wav_header[17] << 8) | ||
| 145 : | + wav_header[16]; | ||
| 146 : | } | ||
| 147 : | else if (!(strncmp((char *)&(wav_header[0]),"data",4))) | ||
| 148 : | { | ||
| 149 : | raw_data_length = chunk_length; | ||
| 150 : | } | ||
| 151 : | file_pos += (chunk_length + 8); | ||
| 152 : | chunk_length = 0; | ||
| 153 : | } | ||
| 154 : | //**************** | ||
| 155 : | infile.close(); | ||
| 156 : | //**************** | ||
| 157 : | |||
| 158 : | if (!uncompressed_pcm) | ||
| 159 : | { | ||
| 160 : | error_msg = "SoundFileNotPCM"; | ||
| 161 : | return(LLVORBISENC_PCM_FORMAT_ERR); | ||
| 162 : | } | ||
| 163 : | |||
| 164 : | if ((num_channels < 1) || (num_channels > 2)) | ||
| 165 : | { | ||
| 166 : | error_msg = "SoundFileInvalidChannelCount"; | ||
| 167 : | return(LLVORBISENC_MULTICHANNEL_ERR); | ||
| 168 : | } | ||
| 169 : | |||
| 170 : | if (sample_rate != 44100) | ||
| 171 : | { | ||
| 172 : | error_msg = "SoundFileInvalidSampleRate"; | ||
| 173 : | return(LLVORBISENC_UNSUPPORTED_SAMPLE_RATE); | ||
| 174 : | } | ||
| 175 : | |||
| 176 : | if ((bits_per_sample != 16) && (bits_per_sample != 8)) | ||
| 177 : | { | ||
| 178 : | error_msg = "SoundFileInvalidWordSize"; | ||
| 179 : | return(LLVORBISENC_UNSUPPORTED_WORD_SIZE); | ||
| 180 : | } | ||
| 181 : | |||
| 182 : | if (!raw_data_length) | ||
| 183 : | { | ||
| 184 : | error_msg = "SoundFileInvalidHeader"; | ||
| 185 : | return(LLVORBISENC_CLIP_TOO_LONG); | ||
| 186 : | } | ||
| 187 : | |||
| 188 : | F32 clip_length = (F32)raw_data_length/(F32)bytes_per_sec; | ||
| 189 : | |||
| 190 : | if (clip_length > 10.0f) | ||
| 191 : | { | ||
| 192 : | error_msg = "SoundFileInvalidTooLong"; | ||
| 193 : | return(LLVORBISENC_CLIP_TOO_LONG); | ||
| 194 : | } | ||
| 195 : | |||
| 196 : | return(LLVORBISENC_NOERR); | ||
| 197 : | } | ||
| 198 : | |||
| 199 : | S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname) | ||
| 200 : | { | ||
| 201 : | #define READ_BUFFER 1024 | ||
| 202 : | unsigned char readbuffer[READ_BUFFER*4+44]; /* out of the data segment, not the stack */ /*Flawfinder: ignore*/ | ||
| 203 : | |||
| 204 : | ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */ | ||
| 205 : | ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ | ||
| 206 : | ogg_packet op; /* one raw packet of data for decode */ | ||
| 207 : | |||
| 208 : | vorbis_info vi; /* struct that stores all the static vorbis bitstream settings */ | ||
| 209 : | vorbis_comment vc; /* struct that stores all the user comments */ | ||
| 210 : | |||
| 211 : | vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ | ||
| 212 : | vorbis_block vb; /* local working space for packet->PCM decode */ | ||
| 213 : | |||
| 214 : | int eos=0; | ||
| 215 : | int result; | ||
| 216 : | |||
| 217 : | U16 num_channels = 0; | ||
| 218 : | U32 sample_rate = 0; | ||
| 219 : | U32 bits_per_sample = 0; | ||
| 220 : | |||
| 221 : | S32 format_error = 0; | ||
| 222 : | std::string error_msg; | ||
| 223 : | if ((format_error = check_for_invalid_wav_formats(in_fname, error_msg))) | ||
| 224 : | { | ||
| 225 : | llwarns << error_msg << ": " << in_fname << llendl; | ||
| 226 : | return(format_error); | ||
| 227 : | } | ||
| 228 : | |||
| 229 : | #if 1 | ||
| 230 : | unsigned char wav_header[44]; /*Flawfinder: ignore*/ | ||
| 231 : | |||
| 232 : | S32 data_left = 0; | ||
| 233 : | |||
| 234 : | LLAPRFile infile ; | ||
| 235 : | infile.open(in_fname,LL_APR_RB); | ||
| 236 : | if (!infile.getFileHandle()) | ||
| 237 : | { | ||
| 238 : | llwarns << "Couldn't open temporary ogg file for writing: " << in_fname | ||
| 239 : | << llendl; | ||
| 240 : | return(LLVORBISENC_SOURCE_OPEN_ERR); | ||
| 241 : | } | ||
| 242 : | |||
| 243 : | LLAPRFile outfile ; | ||
| 244 : | outfile.open(out_fname,LL_APR_WPB); | ||
| 245 : | if (!outfile.getFileHandle()) | ||
| 246 : | { | ||
| 247 : | llwarns << "Couldn't open upload sound file for reading: " << in_fname | ||
| 248 : | << llendl; | ||
| 249 : | return(LLVORBISENC_DEST_OPEN_ERR); | ||
| 250 : | } | ||
| 251 : | |||
| 252 : | // parse the chunks | ||
| 253 : | U32 chunk_length = 0; | ||
| 254 : | U32 file_pos = 12; // start at the first chunk (usually fmt but not always) | ||
| 255 : | |||
| 256 : | while (infile.eof() != APR_EOF) | ||
| 257 : | { | ||
| 258 : | infile.seek(APR_SET,file_pos); | ||
| 259 : | infile.read(wav_header, 44); | ||
| 260 : | |||
| 261 : | chunk_length = ((U32) wav_header[7] << 24) | ||
| 262 : | + ((U32) wav_header[6] << 16) | ||
| 263 : | + ((U32) wav_header[5] << 8) | ||
| 264 : | + wav_header[4]; | ||
| 265 : | |||
| 266 : | // llinfos << "chunk found: '" << wav_header[0] << wav_header[1] << wav_header[2] << wav_header[3] << "'" << llendl; | ||
| 267 : | |||
| 268 : | if (!(strncmp((char *)&(wav_header[0]),"fmt ",4))) | ||
| 269 : | { | ||
| 270 : | num_channels = ((U16) wav_header[11] << 8) + wav_header[10]; | ||
| 271 : | sample_rate = ((U32) wav_header[15] << 24) | ||
| 272 : | + ((U32) wav_header[14] << 16) | ||
| 273 : | + ((U32) wav_header[13] << 8) | ||
| 274 : | + wav_header[12]; | ||
| 275 : | bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22]; | ||
| 276 : | } | ||
| 277 : | else if (!(strncmp((char *)&(wav_header[0]),"data",4))) | ||
| 278 : | { | ||
| 279 : | infile.seek(APR_SET,file_pos+8); | ||
| 280 : | // leave the file pointer at the beginning of the data chunk data | ||
| 281 : | data_left = chunk_length; | ||
| 282 : | break; | ||
| 283 : | } | ||
| 284 : | file_pos += (chunk_length + 8); | ||
| 285 : | chunk_length = 0; | ||
| 286 : | } | ||
| 287 : | |||
| 288 : | |||
| 289 : | /********** Encode setup ************/ | ||
| 290 : | |||
| 291 : | /* choose an encoding mode */ | ||
| 292 : | /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */ | ||
| 293 : | vorbis_info_init(&vi); | ||
| 294 : | |||
| 295 : | // always encode to mono | ||
| 296 : | |||
| 297 : | // SL-52913 & SL-53779 determined this quality level to be our 'good | ||
| 298 : | // enough' general-purpose quality level with a nice low bitrate. | ||
| 299 : | // Equivalent to oggenc -q0.5 | ||
| 300 : | F32 quality = 0.05f; | ||
| 301 : | // quality = (bitrate==128000 ? 0.4f : 0.1); | ||
| 302 : | |||
| 303 : | // if (vorbis_encode_init(&vi, /* num_channels */ 1 ,sample_rate, -1, bitrate, -1)) | ||
| 304 : | if (vorbis_encode_init_vbr(&vi, /* num_channels */ 1 ,sample_rate, quality)) | ||
| 305 : | // if (vorbis_encode_setup_managed(&vi,1,sample_rate,-1,bitrate,-1) || | ||
| 306 : | // vorbis_encode_ctl(&vi,OV_ECTL_RATEMANAGE_AVG,NULL) || | ||
| 307 : | // vorbis_encode_setup_init(&vi)) | ||
| 308 : | { | ||
| 309 : | llwarns << "unable to initialize vorbis codec at quality " << quality << llendl; | ||
| 310 : | // llwarns << "unable to initialize vorbis codec at bitrate " << bitrate << llendl; | ||
| 311 : | return(LLVORBISENC_DEST_OPEN_ERR); | ||
| 312 : | } | ||
| 313 : | |||
| 314 : | /* add a comment */ | ||
| 315 : | vorbis_comment_init(&vc); | ||
| 316 : | // vorbis_comment_add(&vc,"Linden"); | ||
| 317 : | |||
| 318 : | /* set up the analysis state and auxiliary encoding storage */ | ||
| 319 : | vorbis_analysis_init(&vd,&vi); | ||
| 320 : | vorbis_block_init(&vd,&vb); | ||
| 321 : | |||
| 322 : | /* set up our packet->stream encoder */ | ||
| 323 : | /* pick a random serial number; that way we can more likely build | ||
| 324 : | chained streams just by concatenation */ | ||
| 325 : | ogg_stream_init(&os, ll_rand()); | ||
| 326 : | |||
| 327 : | /* Vorbis streams begin with three headers; the initial header (with | ||
| 328 : | most of the codec setup parameters) which is mandated by the Ogg | ||
| 329 : | bitstream spec. The second header holds any comment fields. The | ||
| 330 : | third header holds the bitstream codebook. We merely need to | ||
| 331 : | make the headers, then pass them to libvorbis one at a time; | ||
| 332 : | libvorbis handles the additional Ogg bitstream constraints */ | ||
| 333 : | |||
| 334 : | { | ||
| 335 : | ogg_packet header; | ||
| 336 : | ogg_packet header_comm; | ||
| 337 : | ogg_packet header_code; | ||
| 338 : | |||
| 339 : | vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code); | ||
| 340 : | ogg_stream_packetin(&os,&header); /* automatically placed in its own | ||
| 341 : | page */ | ||
| 342 : | ogg_stream_packetin(&os,&header_comm); | ||
| 343 : | ogg_stream_packetin(&os,&header_code); | ||
| 344 : | |||
| 345 : | /* We don't have to write out here, but doing so makes streaming | ||
| 346 : | * much easier, so we do, flushing ALL pages. This ensures the actual | ||
| 347 : | * audio data will start on a new page | ||
| 348 : | */ | ||
| 349 : | while(!eos){ | ||
| 350 : | int result=ogg_stream_flush(&os,&og); | ||
| 351 : | if(result==0)break; | ||
| 352 : | outfile.write(og.header, og.header_len); | ||
| 353 : | outfile.write(og.body, og.body_len); | ||
| 354 : | } | ||
| 355 : | |||
| 356 : | } | ||
| 357 : | |||
| 358 : | |||
| 359 : | while(!eos) | ||
| 360 : | { | ||
| 361 : | long bytes_per_sample = bits_per_sample/8; | ||
| 362 : | |||
| 363 : | long bytes=(long)infile.read(readbuffer,llclamp((S32)(READ_BUFFER*num_channels*bytes_per_sample),0,data_left)); /* stereo hardwired here */ | ||
| 364 : | |||
| 365 : | if (bytes==0) | ||
| 366 : | { | ||
| 367 : | /* end of file. this can be done implicitly in the mainline, | ||
| 368 : | but it's easier to see here in non-clever fashion. | ||
| 369 : | Tell the library we're at end of stream so that it can handle | ||
| 370 : | the last frame and mark end of stream in the output properly */ | ||
| 371 : | |||
| 372 : | vorbis_analysis_wrote(&vd,0); | ||
| 373 : | // eos = 1; | ||
| 374 : | |||
| 375 : | } | ||
| 376 : | else | ||
| 377 : | { | ||
| 378 : | long i; | ||
| 379 : | long samples; | ||
| 380 : | int temp; | ||
| 381 : | |||
| 382 : | data_left -= bytes; | ||
| 383 : | /* data to encode */ | ||
| 384 : | |||
| 385 : | /* expose the buffer to submit data */ | ||
| 386 : | float **buffer=vorbis_analysis_buffer(&vd,READ_BUFFER); | ||
| 387 : | |||
| 388 : | i = 0; | ||
| 389 : | samples = bytes / (num_channels * bytes_per_sample); | ||
| 390 : | |||
| 391 : | if (num_channels == 2) | ||
| 392 : | { | ||
| 393 : | if (bytes_per_sample == 2) | ||
| 394 : | { | ||
| 395 : | /* uninterleave samples */ | ||
| 396 : | for(i=0; i<samples ;i++) | ||
| 397 : | { | ||
| 398 : | temp = ((signed char *)readbuffer)[i*4+1]; /*Flawfinder: ignore*/ | ||
| 399 : | temp += ((signed char *)readbuffer)[i*4+3]; /*Flawfinder: ignore*/ | ||
| 400 : | temp <<= 8; | ||
| 401 : | temp += readbuffer[i*4]; | ||
| 402 : | temp += readbuffer[i*4+2]; | ||
| 403 : | |||
| 404 : | buffer[0][i] = ((float)temp) / 65536.f; | ||
| 405 : | } | ||
| 406 : | } | ||
| 407 : | else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard") | ||
| 408 : | { | ||
| 409 : | /* uninterleave samples */ | ||
| 410 : | for(i=0; i<samples ;i++) | ||
| 411 : | { | ||
| 412 : | temp = readbuffer[i*2+0]; | ||
| 413 : | temp += readbuffer[i*2+1]; | ||
| 414 : | temp -= 256; | ||
| 415 : | buffer[0][i] = ((float)temp) / 256.f; | ||
| 416 : | } | ||
| 417 : | } | ||
| 418 : | } | ||
| 419 : | else if (num_channels == 1) | ||
| 420 : | { | ||
| 421 : | if (bytes_per_sample == 2) | ||
| 422 : | { | ||
| 423 : | for(i=0; i < samples ;i++) | ||
| 424 : | { | ||
| 425 : | temp = ((signed char*)readbuffer)[i*2+1]; | ||
| 426 : | temp <<= 8; | ||
| 427 : | temp += readbuffer[i*2]; | ||
| 428 : | buffer[0][i] = ((float)temp) / 32768.f; | ||
| 429 : | } | ||
| 430 : | } | ||
| 431 : | else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard") | ||
| 432 : | { | ||
| 433 : | for(i=0; i < samples ;i++) | ||
| 434 : | { | ||
| 435 : | temp = readbuffer[i]; | ||
| 436 : | temp -= 128; | ||
| 437 : | buffer[0][i] = ((float)temp) / 128.f; | ||
| 438 : | } | ||
| 439 : | } | ||
| 440 : | } | ||
| 441 : | |||
| 442 : | /* tell the library how much we actually submitted */ | ||
| 443 : | vorbis_analysis_wrote(&vd,i); | ||
| 444 : | } | ||
| 445 : | |||
| 446 : | /* vorbis does some data preanalysis, then divvies up blocks for | ||
| 447 : | more involved (potentially parallel) processing. Get a single | ||
| 448 : | block for encoding now */ | ||
| 449 : | while(vorbis_analysis_blockout(&vd,&vb)==1) | ||
| 450 : | { | ||
| 451 : | |||
| 452 : | /* analysis */ | ||
| 453 : | /* Do the main analysis, creating a packet */ | ||
| 454 : | vorbis_analysis(&vb, NULL); | ||
| 455 : | vorbis_bitrate_addblock(&vb); | ||
| 456 : | |||
| 457 : | while(vorbis_bitrate_flushpacket(&vd, &op)) | ||
| 458 : | { | ||
| 459 : | |||
| 460 : | /* weld the packet into the bitstream */ | ||
| 461 : | ogg_stream_packetin(&os,&op); | ||
| 462 : | |||
| 463 : | /* write out pages (if any) */ | ||
| 464 : | while(!eos) | ||
| 465 : | { | ||
| 466 : | result = ogg_stream_pageout(&os,&og); | ||
| 467 : | |||
| 468 : | if(result==0) | ||
| 469 : | break; | ||
| 470 : | |||
| 471 : | outfile.write(og.header, og.header_len); | ||
| 472 : | outfile.write(og.body, og.body_len); | ||
| 473 : | |||
| 474 : | /* this could be set above, but for illustrative purposes, I do | ||
| 475 : | it here (to show that vorbis does know where the stream ends) */ | ||
| 476 : | |||
| 477 : | if(ogg_page_eos(&og)) | ||
| 478 : | eos=1; | ||
| 479 : | |||
| 480 : | } | ||
| 481 : | } | ||
| 482 : | } | ||
| 483 : | } | ||
| 484 : | |||
| 485 : | |||
| 486 : | |||
| 487 : | /* clean up and exit. vorbis_info_clear() must be called last */ | ||
| 488 : | |||
| 489 : | ogg_stream_clear(&os); | ||
| 490 : | vorbis_block_clear(&vb); | ||
| 491 : | vorbis_dsp_clear(&vd); | ||
| 492 : | vorbis_comment_clear(&vc); | ||
| 493 : | vorbis_info_clear(&vi); | ||
| 494 : | |||
| 495 : | /* ogg_page and ogg_packet structs always point to storage in | ||
| 496 : | libvorbis. They're never freed or manipulated directly */ | ||
| 497 : | |||
| 498 : | // fprintf(stderr,"Vorbis encoding: Done.\n"); | ||
| 499 : | llinfos << "Vorbis encoding: Done." << llendl; | ||
| 500 : | |||
| 501 : | #endif | ||
| 502 : | return(LLVORBISENC_NOERR); | ||
| 503 : | |||
| 504 : | } |
| ViewVC Help | |
| Powered by ViewVC 1.0.0 |

