1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/modules/media_file/source/media_file_utility.h" 12 13 #include <assert.h> 14 #include <sys/stat.h> 15 #include <sys/types.h> 16 17 #include "webrtc/common_types.h" 18 #include "webrtc/engine_configurations.h" 19 #include "webrtc/modules/interface/module_common_types.h" 20 #include "webrtc/system_wrappers/interface/file_wrapper.h" 21 #include "webrtc/system_wrappers/interface/trace.h" 22 23 #ifdef WEBRTC_MODULE_UTILITY_VIDEO 24 #include "avi_file.h" 25 #endif 26 27 namespace { 28 enum WaveFormats 29 { 30 kWaveFormatPcm = 0x0001, 31 kWaveFormatALaw = 0x0006, 32 kWaveFormatMuLaw = 0x0007 33 }; 34 35 // First 16 bytes the WAVE header. ckID should be "RIFF", wave_ckID should be 36 // "WAVE" and ckSize is the chunk size (4 + n) 37 struct WAVE_RIFF_header 38 { 39 int8_t ckID[4]; 40 int32_t ckSize; 41 int8_t wave_ckID[4]; 42 }; 43 44 // First 8 byte of the format chunk. fmt_ckID should be "fmt ". fmt_ckSize is 45 // the chunk size (16, 18 or 40 byte) 46 struct WAVE_CHUNK_header 47 { 48 int8_t fmt_ckID[4]; 49 int32_t fmt_ckSize; 50 }; 51 } // unnamed namespace 52 53 namespace webrtc { 54 ModuleFileUtility::ModuleFileUtility(const int32_t id) 55 : _wavFormatObj(), 56 _dataSize(0), 57 _readSizeBytes(0), 58 _id(id), 59 _stopPointInMs(0), 60 _startPointInMs(0), 61 _playoutPositionMs(0), 62 _bytesWritten(0), 63 codec_info_(), 64 _codecId(kCodecNoCodec), 65 _bytesPerSample(0), 66 _readPos(0), 67 _reading(false), 68 _writing(false), 69 _tempData() 70 #ifdef WEBRTC_MODULE_UTILITY_VIDEO 71 , 72 _aviAudioInFile(0), 73 _aviVideoInFile(0), 74 _aviOutFile(0) 75 #endif 76 { 77 WEBRTC_TRACE(kTraceMemory, kTraceFile, _id, 78 "ModuleFileUtility::ModuleFileUtility()"); 79 memset(&codec_info_,0,sizeof(CodecInst)); 80 codec_info_.pltype = -1; 81 #ifdef WEBRTC_MODULE_UTILITY_VIDEO 82 memset(&_videoCodec,0,sizeof(_videoCodec)); 83 #endif 84 } 85 86 ModuleFileUtility::~ModuleFileUtility() 87 { 88 WEBRTC_TRACE(kTraceMemory, kTraceFile, _id, 89 "ModuleFileUtility::~ModuleFileUtility()"); 90 #ifdef WEBRTC_MODULE_UTILITY_VIDEO 91 delete _aviAudioInFile; 92 delete _aviVideoInFile; 93 #endif 94 } 95 96 #ifdef WEBRTC_MODULE_UTILITY_VIDEO 97 int32_t ModuleFileUtility::InitAviWriting( 98 const char* filename, 99 const CodecInst& audioCodecInst, 100 const VideoCodec& videoCodecInst, 101 const bool videoOnly /*= false*/) 102 { 103 _writing = false; 104 105 delete _aviOutFile; 106 _aviOutFile = new AviFile( ); 107 108 AVISTREAMHEADER videoStreamHeader; 109 videoStreamHeader.fccType = AviFile::MakeFourCc('v', 'i', 'd', 's'); 110 111 #ifdef VIDEOCODEC_I420 112 if (strncmp(videoCodecInst.plName, "I420", 7) == 0) 113 { 114 videoStreamHeader.fccHandler = AviFile::MakeFourCc('I','4','2','0'); 115 } 116 #endif 117 #ifdef VIDEOCODEC_VP8 118 if (strncmp(videoCodecInst.plName, "VP8", 7) == 0) 119 { 120 videoStreamHeader.fccHandler = AviFile::MakeFourCc('V','P','8','0'); 121 } 122 #endif 123 if (videoStreamHeader.fccHandler == 0) 124 { 125 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 126 "InitAviWriting() Codec not supported"); 127 128 return -1; 129 } 130 videoStreamHeader.dwScale = 1; 131 videoStreamHeader.dwRate = videoCodecInst.maxFramerate; 132 videoStreamHeader.dwSuggestedBufferSize = videoCodecInst.height * 133 (videoCodecInst.width >> 1) * 3; 134 videoStreamHeader.dwQuality = (uint32_t)-1; 135 videoStreamHeader.dwSampleSize = 0; 136 videoStreamHeader.rcFrame.top = 0; 137 videoStreamHeader.rcFrame.bottom = videoCodecInst.height; 138 videoStreamHeader.rcFrame.left = 0; 139 videoStreamHeader.rcFrame.right = videoCodecInst.width; 140 141 BITMAPINFOHEADER bitMapInfoHeader; 142 bitMapInfoHeader.biSize = sizeof(BITMAPINFOHEADER); 143 bitMapInfoHeader.biHeight = videoCodecInst.height; 144 bitMapInfoHeader.biWidth = videoCodecInst.width; 145 bitMapInfoHeader.biPlanes = 1; 146 bitMapInfoHeader.biBitCount = 12; 147 bitMapInfoHeader.biClrImportant = 0; 148 bitMapInfoHeader.biClrUsed = 0; 149 bitMapInfoHeader.biCompression = videoStreamHeader.fccHandler; 150 bitMapInfoHeader.biSizeImage = bitMapInfoHeader.biWidth * 151 bitMapInfoHeader.biHeight * bitMapInfoHeader.biBitCount / 8; 152 153 if (_aviOutFile->CreateVideoStream( 154 videoStreamHeader, 155 bitMapInfoHeader, 156 NULL, 157 0) != 0) 158 { 159 return -1; 160 } 161 162 if(!videoOnly) 163 { 164 AVISTREAMHEADER audioStreamHeader; 165 audioStreamHeader.fccType = AviFile::MakeFourCc('a', 'u', 'd', 's'); 166 // fccHandler is the FOURCC of the codec for decoding the stream. 167 // It's an optional parameter that is not used by audio streams. 168 audioStreamHeader.fccHandler = 0; 169 audioStreamHeader.dwScale = 1; 170 171 WAVEFORMATEX waveFormatHeader; 172 waveFormatHeader.cbSize = 0; 173 waveFormatHeader.nChannels = 1; 174 175 if (strncmp(audioCodecInst.plname, "PCMU", 4) == 0) 176 { 177 audioStreamHeader.dwSampleSize = 1; 178 audioStreamHeader.dwRate = 8000; 179 audioStreamHeader.dwQuality = (uint32_t)-1; 180 audioStreamHeader.dwSuggestedBufferSize = 80; 181 182 waveFormatHeader.nAvgBytesPerSec = 8000; 183 waveFormatHeader.nSamplesPerSec = 8000; 184 waveFormatHeader.wBitsPerSample = 8; 185 waveFormatHeader.nBlockAlign = 1; 186 waveFormatHeader.wFormatTag = kWaveFormatMuLaw; 187 188 } else if (strncmp(audioCodecInst.plname, "PCMA", 4) == 0) 189 { 190 audioStreamHeader.dwSampleSize = 1; 191 audioStreamHeader.dwRate = 8000; 192 audioStreamHeader.dwQuality = (uint32_t)-1; 193 audioStreamHeader.dwSuggestedBufferSize = 80; 194 195 waveFormatHeader.nAvgBytesPerSec = 8000; 196 waveFormatHeader.nSamplesPerSec = 8000; 197 waveFormatHeader.wBitsPerSample = 8; 198 waveFormatHeader.nBlockAlign = 1; 199 waveFormatHeader.wFormatTag = kWaveFormatALaw; 200 201 } else if (strncmp(audioCodecInst.plname, "L16", 3) == 0) 202 { 203 audioStreamHeader.dwSampleSize = 2; 204 audioStreamHeader.dwRate = audioCodecInst.plfreq; 205 audioStreamHeader.dwQuality = (uint32_t)-1; 206 audioStreamHeader.dwSuggestedBufferSize = 207 (audioCodecInst.plfreq/100) * 2; 208 209 waveFormatHeader.nAvgBytesPerSec = audioCodecInst.plfreq * 2; 210 waveFormatHeader.nSamplesPerSec = audioCodecInst.plfreq; 211 waveFormatHeader.wBitsPerSample = 16; 212 waveFormatHeader.nBlockAlign = 2; 213 waveFormatHeader.wFormatTag = kWaveFormatPcm; 214 } else 215 { 216 return -1; 217 } 218 219 if(_aviOutFile->CreateAudioStream( 220 audioStreamHeader, 221 waveFormatHeader) != 0) 222 { 223 return -1; 224 } 225 226 227 if( InitWavCodec(waveFormatHeader.nSamplesPerSec, 228 waveFormatHeader.nChannels, 229 waveFormatHeader.wBitsPerSample, 230 waveFormatHeader.wFormatTag) != 0) 231 { 232 return -1; 233 } 234 } 235 _aviOutFile->Create(filename); 236 _writing = true; 237 return 0; 238 } 239 240 int32_t ModuleFileUtility::WriteAviAudioData( 241 const int8_t* buffer, 242 uint32_t bufferLengthInBytes) 243 { 244 if( _aviOutFile != 0) 245 { 246 return _aviOutFile->WriteAudio( 247 reinterpret_cast<const uint8_t*>(buffer), 248 bufferLengthInBytes); 249 } 250 else 251 { 252 WEBRTC_TRACE(kTraceError, kTraceFile, _id, "AVI file not initialized"); 253 return -1; 254 } 255 } 256 257 int32_t ModuleFileUtility::WriteAviVideoData( 258 const int8_t* buffer, 259 uint32_t bufferLengthInBytes) 260 { 261 if( _aviOutFile != 0) 262 { 263 return _aviOutFile->WriteVideo( 264 reinterpret_cast<const uint8_t*>(buffer), 265 bufferLengthInBytes); 266 } 267 else 268 { 269 WEBRTC_TRACE(kTraceError, kTraceFile, _id, "AVI file not initialized"); 270 return -1; 271 } 272 } 273 274 275 int32_t ModuleFileUtility::CloseAviFile( ) 276 { 277 if( _reading && _aviAudioInFile) 278 { 279 delete _aviAudioInFile; 280 _aviAudioInFile = 0; 281 } 282 283 if( _reading && _aviVideoInFile) 284 { 285 delete _aviVideoInFile; 286 _aviVideoInFile = 0; 287 } 288 289 if( _writing && _aviOutFile) 290 { 291 delete _aviOutFile; 292 _aviOutFile = 0; 293 } 294 return 0; 295 } 296 297 298 int32_t ModuleFileUtility::InitAviReading(const char* filename, bool videoOnly, 299 bool loop) 300 { 301 _reading = false; 302 delete _aviVideoInFile; 303 _aviVideoInFile = new AviFile( ); 304 305 if ((_aviVideoInFile != 0) && _aviVideoInFile->Open(AviFile::AVI_VIDEO, 306 filename, loop) == -1) 307 { 308 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, 309 "Unable to open AVI file (video)"); 310 return -1; 311 } 312 313 314 AVISTREAMHEADER videoInStreamHeader; 315 BITMAPINFOHEADER bitmapInfo; 316 char codecConfigParameters[AviFile::CODEC_CONFIG_LENGTH] = {}; 317 int32_t configLength = 0; 318 if( _aviVideoInFile->GetVideoStreamInfo(videoInStreamHeader, bitmapInfo, 319 codecConfigParameters, 320 configLength) != 0) 321 { 322 return -1; 323 } 324 _videoCodec.width = static_cast<uint16_t>( 325 videoInStreamHeader.rcFrame.right); 326 _videoCodec.height = static_cast<uint16_t>( 327 videoInStreamHeader.rcFrame.bottom); 328 _videoCodec.maxFramerate = static_cast<uint8_t>( 329 videoInStreamHeader.dwRate); 330 331 const size_t plnameLen = sizeof(_videoCodec.plName) / sizeof(char); 332 if (bitmapInfo.biCompression == AviFile::MakeFourCc('I','4','2','0')) 333 { 334 strncpy(_videoCodec.plName, "I420", plnameLen); 335 _videoCodec.codecType = kVideoCodecI420; 336 } 337 else if (bitmapInfo.biCompression == 338 AviFile::MakeFourCc('V', 'P', '8', '0')) 339 { 340 strncpy(_videoCodec.plName, "VP8", plnameLen); 341 _videoCodec.codecType = kVideoCodecVP8; 342 } 343 else 344 { 345 return -1; 346 } 347 348 if(!videoOnly) 349 { 350 delete _aviAudioInFile; 351 _aviAudioInFile = new AviFile(); 352 353 if ( (_aviAudioInFile != 0) && 354 _aviAudioInFile->Open(AviFile::AVI_AUDIO, filename, loop) == -1) 355 { 356 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, 357 "Unable to open AVI file (audio)"); 358 return -1; 359 } 360 361 WAVEFORMATEX waveHeader; 362 if(_aviAudioInFile->GetAudioStreamInfo(waveHeader) != 0) 363 { 364 return -1; 365 } 366 if(InitWavCodec(waveHeader.nSamplesPerSec, waveHeader.nChannels, 367 waveHeader.wBitsPerSample, waveHeader.wFormatTag) != 0) 368 { 369 return -1; 370 } 371 } 372 _reading = true; 373 return 0; 374 } 375 376 int32_t ModuleFileUtility::ReadAviAudioData( 377 int8_t* outBuffer, 378 const uint32_t bufferLengthInBytes) 379 { 380 if(_aviAudioInFile == 0) 381 { 382 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "AVI file not opened."); 383 return -1; 384 } 385 386 int32_t length = bufferLengthInBytes; 387 if(_aviAudioInFile->ReadAudio( 388 reinterpret_cast<uint8_t*>(outBuffer), 389 length) != 0) 390 { 391 return -1; 392 } 393 else 394 { 395 return length; 396 } 397 } 398 399 int32_t ModuleFileUtility::ReadAviVideoData( 400 int8_t* outBuffer, 401 const uint32_t bufferLengthInBytes) 402 { 403 if(_aviVideoInFile == 0) 404 { 405 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "AVI file not opened."); 406 return -1; 407 } 408 409 int32_t length = bufferLengthInBytes; 410 if( _aviVideoInFile->ReadVideo( 411 reinterpret_cast<uint8_t*>(outBuffer), 412 length) != 0) 413 { 414 return -1; 415 } else { 416 return length; 417 } 418 } 419 420 int32_t ModuleFileUtility::VideoCodecInst(VideoCodec& codecInst) 421 { 422 WEBRTC_TRACE(kTraceStream, kTraceFile, _id, 423 "ModuleFileUtility::CodecInst(codecInst= 0x%x)", &codecInst); 424 425 if(!_reading) 426 { 427 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 428 "CodecInst: not currently reading audio file!"); 429 return -1; 430 } 431 memcpy(&codecInst,&_videoCodec,sizeof(VideoCodec)); 432 return 0; 433 } 434 #endif 435 436 int32_t ModuleFileUtility::ReadWavHeader(InStream& wav) 437 { 438 WAVE_RIFF_header RIFFheaderObj; 439 WAVE_CHUNK_header CHUNKheaderObj; 440 // TODO (hellner): tmpStr and tmpStr2 seems unnecessary here. 441 char tmpStr[6] = "FOUR"; 442 unsigned char tmpStr2[4]; 443 int32_t i, len; 444 bool dataFound = false; 445 bool fmtFound = false; 446 int8_t dummyRead; 447 448 449 _dataSize = 0; 450 len = wav.Read(&RIFFheaderObj, sizeof(WAVE_RIFF_header)); 451 if(len != sizeof(WAVE_RIFF_header)) 452 { 453 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 454 "Not a wave file (too short)"); 455 return -1; 456 } 457 458 for (i = 0; i < 4; i++) 459 { 460 tmpStr[i] = RIFFheaderObj.ckID[i]; 461 } 462 if(strcmp(tmpStr, "RIFF") != 0) 463 { 464 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 465 "Not a wave file (does not have RIFF)"); 466 return -1; 467 } 468 for (i = 0; i < 4; i++) 469 { 470 tmpStr[i] = RIFFheaderObj.wave_ckID[i]; 471 } 472 if(strcmp(tmpStr, "WAVE") != 0) 473 { 474 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 475 "Not a wave file (does not have WAVE)"); 476 return -1; 477 } 478 479 len = wav.Read(&CHUNKheaderObj, sizeof(WAVE_CHUNK_header)); 480 481 // WAVE files are stored in little endian byte order. Make sure that the 482 // data can be read on big endian as well. 483 // TODO (hellner): little endian to system byte order should be done in 484 // in a subroutine. 485 memcpy(tmpStr2, &CHUNKheaderObj.fmt_ckSize, 4); 486 CHUNKheaderObj.fmt_ckSize = 487 (int32_t) ((uint32_t) tmpStr2[0] + 488 (((uint32_t)tmpStr2[1])<<8) + 489 (((uint32_t)tmpStr2[2])<<16) + 490 (((uint32_t)tmpStr2[3])<<24)); 491 492 memcpy(tmpStr, CHUNKheaderObj.fmt_ckID, 4); 493 494 while ((len == sizeof(WAVE_CHUNK_header)) && (!fmtFound || !dataFound)) 495 { 496 if(strcmp(tmpStr, "fmt ") == 0) 497 { 498 len = wav.Read(&_wavFormatObj, sizeof(WAVE_FMTINFO_header)); 499 500 memcpy(tmpStr2, &_wavFormatObj.formatTag, 2); 501 _wavFormatObj.formatTag = 502 (WaveFormats) ((uint32_t)tmpStr2[0] + 503 (((uint32_t)tmpStr2[1])<<8)); 504 memcpy(tmpStr2, &_wavFormatObj.nChannels, 2); 505 _wavFormatObj.nChannels = 506 (int16_t) ((uint32_t)tmpStr2[0] + 507 (((uint32_t)tmpStr2[1])<<8)); 508 memcpy(tmpStr2, &_wavFormatObj.nSamplesPerSec, 4); 509 _wavFormatObj.nSamplesPerSec = 510 (int32_t) ((uint32_t)tmpStr2[0] + 511 (((uint32_t)tmpStr2[1])<<8) + 512 (((uint32_t)tmpStr2[2])<<16) + 513 (((uint32_t)tmpStr2[3])<<24)); 514 memcpy(tmpStr2, &_wavFormatObj.nAvgBytesPerSec, 4); 515 _wavFormatObj.nAvgBytesPerSec = 516 (int32_t) ((uint32_t)tmpStr2[0] + 517 (((uint32_t)tmpStr2[1])<<8) + 518 (((uint32_t)tmpStr2[2])<<16) + 519 (((uint32_t)tmpStr2[3])<<24)); 520 memcpy(tmpStr2, &_wavFormatObj.nBlockAlign, 2); 521 _wavFormatObj.nBlockAlign = 522 (int16_t) ((uint32_t)tmpStr2[0] + 523 (((uint32_t)tmpStr2[1])<<8)); 524 memcpy(tmpStr2, &_wavFormatObj.nBitsPerSample, 2); 525 _wavFormatObj.nBitsPerSample = 526 (int16_t) ((uint32_t)tmpStr2[0] + 527 (((uint32_t)tmpStr2[1])<<8)); 528 529 for (i = 0; 530 i < (CHUNKheaderObj.fmt_ckSize - 531 (int32_t)sizeof(WAVE_FMTINFO_header)); 532 i++) 533 { 534 len = wav.Read(&dummyRead, 1); 535 if(len != 1) 536 { 537 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 538 "File corrupted, reached EOF (reading fmt)"); 539 return -1; 540 } 541 } 542 fmtFound = true; 543 } 544 else if(strcmp(tmpStr, "data") == 0) 545 { 546 _dataSize = CHUNKheaderObj.fmt_ckSize; 547 dataFound = true; 548 break; 549 } 550 else 551 { 552 for (i = 0; i < (CHUNKheaderObj.fmt_ckSize); i++) 553 { 554 len = wav.Read(&dummyRead, 1); 555 if(len != 1) 556 { 557 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 558 "File corrupted, reached EOF (reading other)"); 559 return -1; 560 } 561 } 562 } 563 564 len = wav.Read(&CHUNKheaderObj, sizeof(WAVE_CHUNK_header)); 565 566 memcpy(tmpStr2, &CHUNKheaderObj.fmt_ckSize, 4); 567 CHUNKheaderObj.fmt_ckSize = 568 (int32_t) ((uint32_t)tmpStr2[0] + 569 (((uint32_t)tmpStr2[1])<<8) + 570 (((uint32_t)tmpStr2[2])<<16) + 571 (((uint32_t)tmpStr2[3])<<24)); 572 573 memcpy(tmpStr, CHUNKheaderObj.fmt_ckID, 4); 574 } 575 576 // Either a proper format chunk has been read or a data chunk was come 577 // across. 578 if( (_wavFormatObj.formatTag != kWaveFormatPcm) && 579 (_wavFormatObj.formatTag != kWaveFormatALaw) && 580 (_wavFormatObj.formatTag != kWaveFormatMuLaw)) 581 { 582 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 583 "Coding formatTag value=%d not supported!", 584 _wavFormatObj.formatTag); 585 return -1; 586 } 587 if((_wavFormatObj.nChannels < 1) || 588 (_wavFormatObj.nChannels > 2)) 589 { 590 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 591 "nChannels value=%d not supported!", 592 _wavFormatObj.nChannels); 593 return -1; 594 } 595 596 if((_wavFormatObj.nBitsPerSample != 8) && 597 (_wavFormatObj.nBitsPerSample != 16)) 598 { 599 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 600 "nBitsPerSample value=%d not supported!", 601 _wavFormatObj.nBitsPerSample); 602 return -1; 603 } 604 605 // Calculate the number of bytes that 10 ms of audio data correspond to. 606 if(_wavFormatObj.formatTag == kWaveFormatPcm) 607 { 608 // TODO (hellner): integer division for 22050 and 11025 would yield 609 // the same result as the else statement. Remove those 610 // special cases? 611 if(_wavFormatObj.nSamplesPerSec == 44100) 612 { 613 _readSizeBytes = 440 * _wavFormatObj.nChannels * 614 (_wavFormatObj.nBitsPerSample / 8); 615 } else if(_wavFormatObj.nSamplesPerSec == 22050) { 616 _readSizeBytes = 220 * _wavFormatObj.nChannels * 617 (_wavFormatObj.nBitsPerSample / 8); 618 } else if(_wavFormatObj.nSamplesPerSec == 11025) { 619 _readSizeBytes = 110 * _wavFormatObj.nChannels * 620 (_wavFormatObj.nBitsPerSample / 8); 621 } else { 622 _readSizeBytes = (_wavFormatObj.nSamplesPerSec/100) * 623 _wavFormatObj.nChannels * (_wavFormatObj.nBitsPerSample / 8); 624 } 625 626 } else { 627 _readSizeBytes = (_wavFormatObj.nSamplesPerSec/100) * 628 _wavFormatObj.nChannels * (_wavFormatObj.nBitsPerSample / 8); 629 } 630 return 0; 631 } 632 633 int32_t ModuleFileUtility::InitWavCodec(uint32_t samplesPerSec, 634 uint32_t channels, 635 uint32_t bitsPerSample, 636 uint32_t formatTag) 637 { 638 codec_info_.pltype = -1; 639 codec_info_.plfreq = samplesPerSec; 640 codec_info_.channels = channels; 641 codec_info_.rate = bitsPerSample * samplesPerSec; 642 643 // Calculate the packet size for 10ms frames 644 switch(formatTag) 645 { 646 case kWaveFormatALaw: 647 strcpy(codec_info_.plname, "PCMA"); 648 _codecId = kCodecPcma; 649 codec_info_.pltype = 8; 650 codec_info_.pacsize = codec_info_.plfreq / 100; 651 break; 652 case kWaveFormatMuLaw: 653 strcpy(codec_info_.plname, "PCMU"); 654 _codecId = kCodecPcmu; 655 codec_info_.pltype = 0; 656 codec_info_.pacsize = codec_info_.plfreq / 100; 657 break; 658 case kWaveFormatPcm: 659 codec_info_.pacsize = (bitsPerSample * (codec_info_.plfreq / 100)) / 8; 660 if(samplesPerSec == 8000) 661 { 662 strcpy(codec_info_.plname, "L16"); 663 _codecId = kCodecL16_8Khz; 664 } 665 else if(samplesPerSec == 16000) 666 { 667 strcpy(codec_info_.plname, "L16"); 668 _codecId = kCodecL16_16kHz; 669 } 670 else if(samplesPerSec == 32000) 671 { 672 strcpy(codec_info_.plname, "L16"); 673 _codecId = kCodecL16_32Khz; 674 } 675 // Set the packet size for "odd" sampling frequencies so that it 676 // properly corresponds to _readSizeBytes. 677 else if(samplesPerSec == 11025) 678 { 679 strcpy(codec_info_.plname, "L16"); 680 _codecId = kCodecL16_16kHz; 681 codec_info_.pacsize = 110; 682 codec_info_.plfreq = 11000; 683 } 684 else if(samplesPerSec == 22050) 685 { 686 strcpy(codec_info_.plname, "L16"); 687 _codecId = kCodecL16_16kHz; 688 codec_info_.pacsize = 220; 689 codec_info_.plfreq = 22000; 690 } 691 else if(samplesPerSec == 44100) 692 { 693 strcpy(codec_info_.plname, "L16"); 694 _codecId = kCodecL16_16kHz; 695 codec_info_.pacsize = 440; 696 codec_info_.plfreq = 44000; 697 } 698 else if(samplesPerSec == 48000) 699 { 700 strcpy(codec_info_.plname, "L16"); 701 _codecId = kCodecL16_16kHz; 702 codec_info_.pacsize = 480; 703 codec_info_.plfreq = 48000; 704 } 705 else 706 { 707 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 708 "Unsupported PCM frequency!"); 709 return -1; 710 } 711 break; 712 default: 713 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 714 "unknown WAV format TAG!"); 715 return -1; 716 break; 717 } 718 return 0; 719 } 720 721 int32_t ModuleFileUtility::InitWavReading(InStream& wav, 722 const uint32_t start, 723 const uint32_t stop) 724 { 725 726 _reading = false; 727 728 if(ReadWavHeader(wav) == -1) 729 { 730 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 731 "failed to read WAV header!"); 732 return -1; 733 } 734 735 _playoutPositionMs = 0; 736 _readPos = 0; 737 738 if(start > 0) 739 { 740 uint8_t dummy[WAV_MAX_BUFFER_SIZE]; 741 int32_t readLength; 742 if(_readSizeBytes <= WAV_MAX_BUFFER_SIZE) 743 { 744 while (_playoutPositionMs < start) 745 { 746 readLength = wav.Read(dummy, _readSizeBytes); 747 if(readLength == _readSizeBytes) 748 { 749 _readPos += readLength; 750 _playoutPositionMs += 10; 751 } 752 else // Must have reached EOF before start position! 753 { 754 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 755 "InitWavReading(), EOF before start position"); 756 return -1; 757 } 758 } 759 } 760 else 761 { 762 return -1; 763 } 764 } 765 if( InitWavCodec(_wavFormatObj.nSamplesPerSec, _wavFormatObj.nChannels, 766 _wavFormatObj.nBitsPerSample, 767 _wavFormatObj.formatTag) != 0) 768 { 769 return -1; 770 } 771 _bytesPerSample = _wavFormatObj.nBitsPerSample / 8; 772 773 774 _startPointInMs = start; 775 _stopPointInMs = stop; 776 _reading = true; 777 return 0; 778 } 779 780 int32_t ModuleFileUtility::ReadWavDataAsMono( 781 InStream& wav, 782 int8_t* outData, 783 const uint32_t bufferSize) 784 { 785 WEBRTC_TRACE( 786 kTraceStream, 787 kTraceFile, 788 _id, 789 "ModuleFileUtility::ReadWavDataAsMono(wav= 0x%x, outData= 0x%d,\ 790 bufSize= %ld)", 791 &wav, 792 outData, 793 bufferSize); 794 795 // The number of bytes that should be read from file. 796 const uint32_t totalBytesNeeded = _readSizeBytes; 797 // The number of bytes that will be written to outData. 798 const uint32_t bytesRequested = (codec_info_.channels == 2) ? 799 totalBytesNeeded >> 1 : totalBytesNeeded; 800 if(bufferSize < bytesRequested) 801 { 802 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 803 "ReadWavDataAsMono: output buffer is too short!"); 804 return -1; 805 } 806 if(outData == NULL) 807 { 808 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 809 "ReadWavDataAsMono: output buffer NULL!"); 810 return -1; 811 } 812 813 if(!_reading) 814 { 815 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 816 "ReadWavDataAsMono: no longer reading file."); 817 return -1; 818 } 819 820 int32_t bytesRead = ReadWavData( 821 wav, 822 (codec_info_.channels == 2) ? _tempData : (uint8_t*)outData, 823 totalBytesNeeded); 824 if(bytesRead == 0) 825 { 826 return 0; 827 } 828 if(bytesRead < 0) 829 { 830 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 831 "ReadWavDataAsMono: failed to read data from WAV file."); 832 return -1; 833 } 834 // Output data is should be mono. 835 if(codec_info_.channels == 2) 836 { 837 for (uint32_t i = 0; i < bytesRequested / _bytesPerSample; i++) 838 { 839 // Sample value is the average of left and right buffer rounded to 840 // closest integer value. Note samples can be either 1 or 2 byte. 841 if(_bytesPerSample == 1) 842 { 843 _tempData[i] = ((_tempData[2 * i] + _tempData[(2 * i) + 1] + 844 1) >> 1); 845 } 846 else 847 { 848 int16_t* sampleData = (int16_t*) _tempData; 849 sampleData[i] = ((sampleData[2 * i] + sampleData[(2 * i) + 1] + 850 1) >> 1); 851 } 852 } 853 memcpy(outData, _tempData, bytesRequested); 854 } 855 return bytesRequested; 856 } 857 858 int32_t ModuleFileUtility::ReadWavDataAsStereo( 859 InStream& wav, 860 int8_t* outDataLeft, 861 int8_t* outDataRight, 862 const uint32_t bufferSize) 863 { 864 WEBRTC_TRACE( 865 kTraceStream, 866 kTraceFile, 867 _id, 868 "ModuleFileUtility::ReadWavDataAsStereo(wav= 0x%x, outLeft= 0x%x,\ 869 outRight= 0x%x, bufSize= %ld)", 870 &wav, 871 outDataLeft, 872 outDataRight, 873 bufferSize); 874 875 if((outDataLeft == NULL) || 876 (outDataRight == NULL)) 877 { 878 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 879 "ReadWavDataAsMono: an input buffer is NULL!"); 880 return -1; 881 } 882 if(codec_info_.channels != 2) 883 { 884 WEBRTC_TRACE( 885 kTraceError, 886 kTraceFile, 887 _id, 888 "ReadWavDataAsStereo: WAV file does not contain stereo data!"); 889 return -1; 890 } 891 if(! _reading) 892 { 893 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 894 "ReadWavDataAsStereo: no longer reading file."); 895 return -1; 896 } 897 898 // The number of bytes that should be read from file. 899 const uint32_t totalBytesNeeded = _readSizeBytes; 900 // The number of bytes that will be written to the left and the right 901 // buffers. 902 const uint32_t bytesRequested = totalBytesNeeded >> 1; 903 if(bufferSize < bytesRequested) 904 { 905 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 906 "ReadWavData: Output buffers are too short!"); 907 assert(false); 908 return -1; 909 } 910 911 int32_t bytesRead = ReadWavData(wav, _tempData, totalBytesNeeded); 912 if(bytesRead <= 0) 913 { 914 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 915 "ReadWavDataAsStereo: failed to read data from WAV file."); 916 return -1; 917 } 918 919 // Turn interleaved audio to left and right buffer. Note samples can be 920 // either 1 or 2 bytes 921 if(_bytesPerSample == 1) 922 { 923 for (uint32_t i = 0; i < bytesRequested; i++) 924 { 925 outDataLeft[i] = _tempData[2 * i]; 926 outDataRight[i] = _tempData[(2 * i) + 1]; 927 } 928 } 929 else if(_bytesPerSample == 2) 930 { 931 int16_t* sampleData = reinterpret_cast<int16_t*>(_tempData); 932 int16_t* outLeft = reinterpret_cast<int16_t*>(outDataLeft); 933 int16_t* outRight = reinterpret_cast<int16_t*>( 934 outDataRight); 935 936 // Bytes requested to samples requested. 937 uint32_t sampleCount = bytesRequested >> 1; 938 for (uint32_t i = 0; i < sampleCount; i++) 939 { 940 outLeft[i] = sampleData[2 * i]; 941 outRight[i] = sampleData[(2 * i) + 1]; 942 } 943 } else { 944 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 945 "ReadWavStereoData: unsupported sample size %d!", 946 _bytesPerSample); 947 assert(false); 948 return -1; 949 } 950 return bytesRequested; 951 } 952 953 int32_t ModuleFileUtility::ReadWavData( 954 InStream& wav, 955 uint8_t* buffer, 956 const uint32_t dataLengthInBytes) 957 { 958 WEBRTC_TRACE( 959 kTraceStream, 960 kTraceFile, 961 _id, 962 "ModuleFileUtility::ReadWavData(wav= 0x%x, buffer= 0x%x, dataLen= %ld)", 963 &wav, 964 buffer, 965 dataLengthInBytes); 966 967 968 if(buffer == NULL) 969 { 970 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 971 "ReadWavDataAsMono: output buffer NULL!"); 972 return -1; 973 } 974 975 // Make sure that a read won't return too few samples. 976 // TODO (hellner): why not read the remaining bytes needed from the start 977 // of the file? 978 if((_dataSize - _readPos) < (int32_t)dataLengthInBytes) 979 { 980 // Rewind() being -1 may be due to the file not supposed to be looped. 981 if(wav.Rewind() == -1) 982 { 983 _reading = false; 984 return 0; 985 } 986 if(InitWavReading(wav, _startPointInMs, _stopPointInMs) == -1) 987 { 988 _reading = false; 989 return -1; 990 } 991 } 992 993 int32_t bytesRead = wav.Read(buffer, dataLengthInBytes); 994 if(bytesRead < 0) 995 { 996 _reading = false; 997 return -1; 998 } 999 1000 // This should never happen due to earlier sanity checks. 1001 // TODO (hellner): change to an assert and fail here since this should 1002 // never happen... 1003 if(bytesRead < (int32_t)dataLengthInBytes) 1004 { 1005 if((wav.Rewind() == -1) || 1006 (InitWavReading(wav, _startPointInMs, _stopPointInMs) == -1)) 1007 { 1008 _reading = false; 1009 return -1; 1010 } 1011 else 1012 { 1013 bytesRead = wav.Read(buffer, dataLengthInBytes); 1014 if(bytesRead < (int32_t)dataLengthInBytes) 1015 { 1016 _reading = false; 1017 return -1; 1018 } 1019 } 1020 } 1021 1022 _readPos += bytesRead; 1023 1024 // TODO (hellner): Why is dataLengthInBytes let dictate the number of bytes 1025 // to read when exactly 10ms should be read?! 1026 _playoutPositionMs += 10; 1027 if((_stopPointInMs > 0) && 1028 (_playoutPositionMs >= _stopPointInMs)) 1029 { 1030 if((wav.Rewind() == -1) || 1031 (InitWavReading(wav, _startPointInMs, _stopPointInMs) == -1)) 1032 { 1033 _reading = false; 1034 } 1035 } 1036 return bytesRead; 1037 } 1038 1039 int32_t ModuleFileUtility::InitWavWriting(OutStream& wav, 1040 const CodecInst& codecInst) 1041 { 1042 1043 if(set_codec_info(codecInst) != 0) 1044 { 1045 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 1046 "codecInst identifies unsupported codec!"); 1047 return -1; 1048 } 1049 _writing = false; 1050 uint32_t channels = (codecInst.channels == 0) ? 1051 1 : codecInst.channels; 1052 1053 if(STR_CASE_CMP(codecInst.plname, "PCMU") == 0) 1054 { 1055 _bytesPerSample = 1; 1056 if(WriteWavHeader(wav, 8000, _bytesPerSample, channels, 1057 kWaveFormatMuLaw, 0) == -1) 1058 { 1059 return -1; 1060 } 1061 }else if(STR_CASE_CMP(codecInst.plname, "PCMA") == 0) 1062 { 1063 _bytesPerSample = 1; 1064 if(WriteWavHeader(wav, 8000, _bytesPerSample, channels, kWaveFormatALaw, 1065 0) == -1) 1066 { 1067 return -1; 1068 } 1069 } 1070 else if(STR_CASE_CMP(codecInst.plname, "L16") == 0) 1071 { 1072 _bytesPerSample = 2; 1073 if(WriteWavHeader(wav, codecInst.plfreq, _bytesPerSample, channels, 1074 kWaveFormatPcm, 0) == -1) 1075 { 1076 return -1; 1077 } 1078 } 1079 else 1080 { 1081 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 1082 "codecInst identifies unsupported codec for WAV file!"); 1083 return -1; 1084 } 1085 _writing = true; 1086 _bytesWritten = 0; 1087 return 0; 1088 } 1089 1090 int32_t ModuleFileUtility::WriteWavData(OutStream& out, 1091 const int8_t* buffer, 1092 const uint32_t dataLength) 1093 { 1094 WEBRTC_TRACE( 1095 kTraceStream, 1096 kTraceFile, 1097 _id, 1098 "ModuleFileUtility::WriteWavData(out= 0x%x, buf= 0x%x, dataLen= %d)", 1099 &out, 1100 buffer, 1101 dataLength); 1102 1103 if(buffer == NULL) 1104 { 1105 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 1106 "WriteWavData: input buffer NULL!"); 1107 return -1; 1108 } 1109 1110 if(!out.Write(buffer, dataLength)) 1111 { 1112 return -1; 1113 } 1114 _bytesWritten += dataLength; 1115 return dataLength; 1116 } 1117 1118 1119 int32_t ModuleFileUtility::WriteWavHeader( 1120 OutStream& wav, 1121 const uint32_t freq, 1122 const uint32_t bytesPerSample, 1123 const uint32_t channels, 1124 const uint32_t format, 1125 const uint32_t lengthInBytes) 1126 { 1127 1128 // Frame size in bytes for 10 ms of audio. 1129 // TODO (hellner): 44.1 kHz has 440 samples frame size. Doesn't seem to 1130 // be taken into consideration here! 1131 int32_t frameSize = (freq / 100) * bytesPerSample * channels; 1132 1133 // Calculate the number of full frames that the wave file contain. 1134 const int32_t dataLengthInBytes = frameSize * 1135 (lengthInBytes / frameSize); 1136 1137 int8_t tmpStr[4]; 1138 int8_t tmpChar; 1139 uint32_t tmpLong; 1140 1141 memcpy(tmpStr, "RIFF", 4); 1142 wav.Write(tmpStr, 4); 1143 1144 tmpLong = dataLengthInBytes + 36; 1145 tmpChar = (int8_t)(tmpLong); 1146 wav.Write(&tmpChar, 1); 1147 tmpChar = (int8_t)(tmpLong >> 8); 1148 wav.Write(&tmpChar, 1); 1149 tmpChar = (int8_t)(tmpLong >> 16); 1150 wav.Write(&tmpChar, 1); 1151 tmpChar = (int8_t)(tmpLong >> 24); 1152 wav.Write(&tmpChar, 1); 1153 1154 memcpy(tmpStr, "WAVE", 4); 1155 wav.Write(tmpStr, 4); 1156 1157 memcpy(tmpStr, "fmt ", 4); 1158 wav.Write(tmpStr, 4); 1159 1160 tmpChar = 16; 1161 wav.Write(&tmpChar, 1); 1162 tmpChar = 0; 1163 wav.Write(&tmpChar, 1); 1164 tmpChar = 0; 1165 wav.Write(&tmpChar, 1); 1166 tmpChar = 0; 1167 wav.Write(&tmpChar, 1); 1168 1169 tmpChar = (int8_t)(format); 1170 wav.Write(&tmpChar, 1); 1171 tmpChar = 0; 1172 wav.Write(&tmpChar, 1); 1173 1174 tmpChar = (int8_t)(channels); 1175 wav.Write(&tmpChar, 1); 1176 tmpChar = 0; 1177 wav.Write(&tmpChar, 1); 1178 1179 tmpLong = freq; 1180 tmpChar = (int8_t)(tmpLong); 1181 wav.Write(&tmpChar, 1); 1182 tmpChar = (int8_t)(tmpLong >> 8); 1183 wav.Write(&tmpChar, 1); 1184 tmpChar = (int8_t)(tmpLong >> 16); 1185 wav.Write(&tmpChar, 1); 1186 tmpChar = (int8_t)(tmpLong >> 24); 1187 wav.Write(&tmpChar, 1); 1188 1189 // nAverageBytesPerSec = Sample rate * Bytes per sample * Channels 1190 tmpLong = bytesPerSample * freq * channels; 1191 tmpChar = (int8_t)(tmpLong); 1192 wav.Write(&tmpChar, 1); 1193 tmpChar = (int8_t)(tmpLong >> 8); 1194 wav.Write(&tmpChar, 1); 1195 tmpChar = (int8_t)(tmpLong >> 16); 1196 wav.Write(&tmpChar, 1); 1197 tmpChar = (int8_t)(tmpLong >> 24); 1198 wav.Write(&tmpChar, 1); 1199 1200 // nBlockAlign = Bytes per sample * Channels 1201 tmpChar = (int8_t)(bytesPerSample * channels); 1202 wav.Write(&tmpChar, 1); 1203 tmpChar = 0; 1204 wav.Write(&tmpChar, 1); 1205 1206 tmpChar = (int8_t)(bytesPerSample*8); 1207 wav.Write(&tmpChar, 1); 1208 tmpChar = 0; 1209 wav.Write(&tmpChar, 1); 1210 1211 memcpy(tmpStr, "data", 4); 1212 wav.Write(tmpStr, 4); 1213 1214 tmpLong = dataLengthInBytes; 1215 tmpChar = (int8_t)(tmpLong); 1216 wav.Write(&tmpChar, 1); 1217 tmpChar = (int8_t)(tmpLong >> 8); 1218 wav.Write(&tmpChar, 1); 1219 tmpChar = (int8_t)(tmpLong >> 16); 1220 wav.Write(&tmpChar, 1); 1221 tmpChar = (int8_t)(tmpLong >> 24); 1222 wav.Write(&tmpChar, 1); 1223 1224 return 0; 1225 } 1226 1227 int32_t ModuleFileUtility::UpdateWavHeader(OutStream& wav) 1228 { 1229 int32_t res = -1; 1230 if(wav.Rewind() == -1) 1231 { 1232 return -1; 1233 } 1234 uint32_t channels = (codec_info_.channels == 0) ? 1235 1 : codec_info_.channels; 1236 1237 if(STR_CASE_CMP(codec_info_.plname, "L16") == 0) 1238 { 1239 res = WriteWavHeader(wav, codec_info_.plfreq, 2, channels, 1240 kWaveFormatPcm, _bytesWritten); 1241 } else if(STR_CASE_CMP(codec_info_.plname, "PCMU") == 0) { 1242 res = WriteWavHeader(wav, 8000, 1, channels, kWaveFormatMuLaw, 1243 _bytesWritten); 1244 } else if(STR_CASE_CMP(codec_info_.plname, "PCMA") == 0) { 1245 res = WriteWavHeader(wav, 8000, 1, channels, kWaveFormatALaw, 1246 _bytesWritten); 1247 } else { 1248 // Allow calling this API even if not writing to a WAVE file. 1249 // TODO (hellner): why?! 1250 return 0; 1251 } 1252 return res; 1253 } 1254 1255 1256 int32_t ModuleFileUtility::InitPreEncodedReading(InStream& in, 1257 const CodecInst& cinst) 1258 { 1259 1260 uint8_t preEncodedID; 1261 in.Read(&preEncodedID, 1); 1262 1263 MediaFileUtility_CodecType codecType = 1264 (MediaFileUtility_CodecType)preEncodedID; 1265 1266 if(set_codec_info(cinst) != 0) 1267 { 1268 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 1269 "Pre-encoded file send codec mismatch!"); 1270 return -1; 1271 } 1272 if(codecType != _codecId) 1273 { 1274 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 1275 "Pre-encoded file format codec mismatch!"); 1276 return -1; 1277 } 1278 memcpy(&codec_info_,&cinst,sizeof(CodecInst)); 1279 _reading = true; 1280 return 0; 1281 } 1282 1283 int32_t ModuleFileUtility::ReadPreEncodedData( 1284 InStream& in, 1285 int8_t* outData, 1286 const uint32_t bufferSize) 1287 { 1288 WEBRTC_TRACE( 1289 kTraceStream, 1290 kTraceFile, 1291 _id, 1292 "ModuleFileUtility::ReadPreEncodedData(in= 0x%x, outData= 0x%x,\ 1293 bufferSize= %d)", 1294 &in, 1295 outData, 1296 bufferSize); 1297 1298 if(outData == NULL) 1299 { 1300 WEBRTC_TRACE(kTraceError, kTraceFile, _id, "output buffer NULL"); 1301 } 1302 1303 uint32_t frameLen; 1304 uint8_t buf[64]; 1305 // Each frame has a two byte header containing the frame length. 1306 int32_t res = in.Read(buf, 2); 1307 if(res != 2) 1308 { 1309 if(!in.Rewind()) 1310 { 1311 // The first byte is the codec identifier. 1312 in.Read(buf, 1); 1313 res = in.Read(buf, 2); 1314 } 1315 else 1316 { 1317 return -1; 1318 } 1319 } 1320 frameLen = buf[0] + buf[1] * 256; 1321 if(bufferSize < frameLen) 1322 { 1323 WEBRTC_TRACE( 1324 kTraceError, 1325 kTraceFile, 1326 _id, 1327 "buffer not large enough to read %d bytes of pre-encoded data!", 1328 frameLen); 1329 return -1; 1330 } 1331 return in.Read(outData, frameLen); 1332 } 1333 1334 int32_t ModuleFileUtility::InitPreEncodedWriting( 1335 OutStream& out, 1336 const CodecInst& codecInst) 1337 { 1338 1339 if(set_codec_info(codecInst) != 0) 1340 { 1341 WEBRTC_TRACE(kTraceError, kTraceFile, _id, "CodecInst not recognized!"); 1342 return -1; 1343 } 1344 _writing = true; 1345 _bytesWritten = 1; 1346 out.Write(&_codecId, 1); 1347 return 0; 1348 } 1349 1350 int32_t ModuleFileUtility::WritePreEncodedData( 1351 OutStream& out, 1352 const int8_t* buffer, 1353 const uint32_t dataLength) 1354 { 1355 WEBRTC_TRACE( 1356 kTraceStream, 1357 kTraceFile, 1358 _id, 1359 "ModuleFileUtility::WritePreEncodedData(out= 0x%x, inData= 0x%x,\ 1360 dataLen= %d)", 1361 &out, 1362 buffer, 1363 dataLength); 1364 1365 if(buffer == NULL) 1366 { 1367 WEBRTC_TRACE(kTraceError, kTraceFile, _id,"buffer NULL"); 1368 } 1369 1370 int32_t bytesWritten = 0; 1371 // The first two bytes is the size of the frame. 1372 int16_t lengthBuf; 1373 lengthBuf = (int16_t)dataLength; 1374 if(!out.Write(&lengthBuf, 2)) 1375 { 1376 return -1; 1377 } 1378 bytesWritten = 2; 1379 1380 if(!out.Write(buffer, dataLength)) 1381 { 1382 return -1; 1383 } 1384 bytesWritten += dataLength; 1385 return bytesWritten; 1386 } 1387 1388 int32_t ModuleFileUtility::InitCompressedReading( 1389 InStream& in, 1390 const uint32_t start, 1391 const uint32_t stop) 1392 { 1393 WEBRTC_TRACE( 1394 kTraceDebug, 1395 kTraceFile, 1396 _id, 1397 "ModuleFileUtility::InitCompressedReading(in= 0x%x, start= %d,\ 1398 stop= %d)", 1399 &in, 1400 start, 1401 stop); 1402 1403 #if defined(WEBRTC_CODEC_AMR) || defined(WEBRTC_CODEC_AMRWB) || \ 1404 defined(WEBRTC_CODEC_ILBC) 1405 int16_t read_len = 0; 1406 #endif 1407 _codecId = kCodecNoCodec; 1408 _playoutPositionMs = 0; 1409 _reading = false; 1410 1411 _startPointInMs = start; 1412 _stopPointInMs = stop; 1413 1414 #ifdef WEBRTC_CODEC_AMR 1415 int32_t AMRmode2bytes[9]={12,13,15,17,19,20,26,31,5}; 1416 #endif 1417 #ifdef WEBRTC_CODEC_AMRWB 1418 int32_t AMRWBmode2bytes[10]={17,23,32,36,40,46,50,58,60,6}; 1419 #endif 1420 1421 // Read the codec name 1422 int32_t cnt = 0; 1423 char buf[64]; 1424 do 1425 { 1426 in.Read(&buf[cnt++], 1); 1427 } while ((buf[cnt-1] != '\n') && (64 > cnt)); 1428 1429 if(cnt==64) 1430 { 1431 return -1; 1432 } else { 1433 buf[cnt]=0; 1434 } 1435 1436 #ifdef WEBRTC_CODEC_AMR 1437 if(!strcmp("#!AMR\n", buf)) 1438 { 1439 strcpy(codec_info_.plname, "amr"); 1440 codec_info_.pacsize = 160; 1441 _codecId = kCodecAmr; 1442 codec_info_.pltype = 112; 1443 codec_info_.rate = 12200; 1444 codec_info_.plfreq = 8000; 1445 codec_info_.channels = 1; 1446 1447 int16_t mode = 0; 1448 if(_startPointInMs > 0) 1449 { 1450 while (_playoutPositionMs <= _startPointInMs) 1451 { 1452 // First read byte contain the AMR mode. 1453 read_len = in.Read(buf, 1); 1454 if(read_len != 1) 1455 { 1456 return -1; 1457 } 1458 1459 mode = (buf[0]>>3)&0xF; 1460 if((mode < 0) || (mode > 8)) 1461 { 1462 if(mode != 15) 1463 { 1464 return -1; 1465 } 1466 } 1467 if(mode != 15) 1468 { 1469 read_len = in.Read(&buf[1], AMRmode2bytes[mode]); 1470 if(read_len != AMRmode2bytes[mode]) 1471 { 1472 return -1; 1473 } 1474 } 1475 _playoutPositionMs += 20; 1476 } 1477 } 1478 } 1479 #endif 1480 #ifdef WEBRTC_CODEC_AMRWB 1481 if(!strcmp("#!AMRWB\n", buf)) 1482 { 1483 strcpy(codec_info_.plname, "amr-wb"); 1484 codec_info_.pacsize = 320; 1485 _codecId = kCodecAmrWb; 1486 codec_info_.pltype = 120; 1487 codec_info_.rate = 20000; 1488 codec_info_.plfreq = 16000; 1489 codec_info_.channels = 1; 1490 1491 int16_t mode = 0; 1492 if(_startPointInMs > 0) 1493 { 1494 while (_playoutPositionMs <= _startPointInMs) 1495 { 1496 // First read byte contain the AMR mode. 1497 read_len = in.Read(buf, 1); 1498 if(read_len != 1) 1499 { 1500 return -1; 1501 } 1502 1503 mode = (buf[0]>>3)&0xF; 1504 if((mode < 0) || (mode > 9)) 1505 { 1506 if(mode != 15) 1507 { 1508 return -1; 1509 } 1510 } 1511 if(mode != 15) 1512 { 1513 read_len = in.Read(&buf[1], AMRWBmode2bytes[mode]); 1514 if(read_len != AMRWBmode2bytes[mode]) 1515 { 1516 return -1; 1517 } 1518 } 1519 _playoutPositionMs += 20; 1520 } 1521 } 1522 } 1523 #endif 1524 #ifdef WEBRTC_CODEC_ILBC 1525 if(!strcmp("#!iLBC20\n", buf)) 1526 { 1527 codec_info_.pltype = 102; 1528 strcpy(codec_info_.plname, "ilbc"); 1529 codec_info_.plfreq = 8000; 1530 codec_info_.pacsize = 160; 1531 codec_info_.channels = 1; 1532 codec_info_.rate = 13300; 1533 _codecId = kCodecIlbc20Ms; 1534 1535 if(_startPointInMs > 0) 1536 { 1537 while (_playoutPositionMs <= _startPointInMs) 1538 { 1539 read_len = in.Read(buf, 38); 1540 if(read_len == 38) 1541 { 1542 _playoutPositionMs += 20; 1543 } 1544 else 1545 { 1546 return -1; 1547 } 1548 } 1549 } 1550 } 1551 1552 if(!strcmp("#!iLBC30\n", buf)) 1553 { 1554 codec_info_.pltype = 102; 1555 strcpy(codec_info_.plname, "ilbc"); 1556 codec_info_.plfreq = 8000; 1557 codec_info_.pacsize = 240; 1558 codec_info_.channels = 1; 1559 codec_info_.rate = 13300; 1560 _codecId = kCodecIlbc30Ms; 1561 1562 if(_startPointInMs > 0) 1563 { 1564 while (_playoutPositionMs <= _startPointInMs) 1565 { 1566 read_len = in.Read(buf, 50); 1567 if(read_len == 50) 1568 { 1569 _playoutPositionMs += 20; 1570 } 1571 else 1572 { 1573 return -1; 1574 } 1575 } 1576 } 1577 } 1578 #endif 1579 if(_codecId == kCodecNoCodec) 1580 { 1581 return -1; 1582 } 1583 _reading = true; 1584 return 0; 1585 } 1586 1587 int32_t ModuleFileUtility::ReadCompressedData(InStream& in, 1588 int8_t* outData, 1589 uint32_t bufferSize) 1590 { 1591 WEBRTC_TRACE( 1592 kTraceStream, 1593 kTraceFile, 1594 _id, 1595 "ModuleFileUtility::ReadCompressedData(in=0x%x, outData=0x%x,\ 1596 bytes=%ld)", 1597 &in, 1598 outData, 1599 bufferSize); 1600 1601 #ifdef WEBRTC_CODEC_AMR 1602 uint32_t AMRmode2bytes[9]={12,13,15,17,19,20,26,31,5}; 1603 #endif 1604 #ifdef WEBRTC_CODEC_AMRWB 1605 uint32_t AMRWBmode2bytes[10]={17,23,32,36,40,46,50,58,60,6}; 1606 #endif 1607 uint32_t bytesRead = 0; 1608 1609 if(! _reading) 1610 { 1611 WEBRTC_TRACE(kTraceError, kTraceFile, _id, "not currently reading!"); 1612 return -1; 1613 } 1614 1615 #ifdef WEBRTC_CODEC_AMR 1616 if(_codecId == kCodecAmr) 1617 { 1618 int32_t res = in.Read(outData, 1); 1619 if(res != 1) 1620 { 1621 if(!in.Rewind()) 1622 { 1623 InitCompressedReading(in, _startPointInMs, _stopPointInMs); 1624 res = in.Read(outData, 1); 1625 if(res != 1) 1626 { 1627 _reading = false; 1628 return -1; 1629 } 1630 } 1631 else 1632 { 1633 _reading = false; 1634 return -1; 1635 } 1636 } 1637 const int16_t mode = (outData[0]>>3)&0xF; 1638 if((mode < 0) || 1639 (mode > 8)) 1640 { 1641 if(mode != 15) 1642 { 1643 return -1; 1644 } 1645 } 1646 if(mode != 15) 1647 { 1648 if(bufferSize < AMRmode2bytes[mode] + 1) 1649 { 1650 WEBRTC_TRACE( 1651 kTraceError, 1652 kTraceFile, 1653 _id, 1654 "output buffer is too short to read AMR compressed data."); 1655 assert(false); 1656 return -1; 1657 } 1658 bytesRead = in.Read(&outData[1], AMRmode2bytes[mode]); 1659 if(bytesRead != AMRmode2bytes[mode]) 1660 { 1661 _reading = false; 1662 return -1; 1663 } 1664 // Count the mode byte to bytes read. 1665 bytesRead++; 1666 } 1667 else 1668 { 1669 bytesRead = 1; 1670 } 1671 } 1672 #endif 1673 #ifdef WEBRTC_CODEC_AMRWB 1674 if(_codecId == kCodecAmrWb) 1675 { 1676 int32_t res = in.Read(outData, 1); 1677 if(res != 1) 1678 { 1679 if(!in.Rewind()) 1680 { 1681 InitCompressedReading(in, _startPointInMs, _stopPointInMs); 1682 res = in.Read(outData, 1); 1683 if(res != 1) 1684 { 1685 _reading = false; 1686 return -1; 1687 } 1688 } 1689 else 1690 { 1691 _reading = false; 1692 return -1; 1693 } 1694 } 1695 int16_t mode = (outData[0]>>3)&0xF; 1696 if((mode < 0) || 1697 (mode > 8)) 1698 { 1699 if(mode != 15) 1700 { 1701 return -1; 1702 } 1703 } 1704 if(mode != 15) 1705 { 1706 if(bufferSize < AMRWBmode2bytes[mode] + 1) 1707 { 1708 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 1709 "output buffer is too short to read AMRWB\ 1710 compressed."); 1711 assert(false); 1712 return -1; 1713 } 1714 bytesRead = in.Read(&outData[1], AMRWBmode2bytes[mode]); 1715 if(bytesRead != AMRWBmode2bytes[mode]) 1716 { 1717 _reading = false; 1718 return -1; 1719 } 1720 bytesRead++; 1721 } 1722 else 1723 { 1724 bytesRead = 1; 1725 } 1726 } 1727 #endif 1728 #ifdef WEBRTC_CODEC_ILBC 1729 if((_codecId == kCodecIlbc20Ms) || 1730 (_codecId == kCodecIlbc30Ms)) 1731 { 1732 uint32_t byteSize = 0; 1733 if(_codecId == kCodecIlbc30Ms) 1734 { 1735 byteSize = 50; 1736 } 1737 if(_codecId == kCodecIlbc20Ms) 1738 { 1739 byteSize = 38; 1740 } 1741 if(bufferSize < byteSize) 1742 { 1743 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 1744 "output buffer is too short to read ILBC compressed\ 1745 data."); 1746 assert(false); 1747 return -1; 1748 } 1749 1750 bytesRead = in.Read(outData, byteSize); 1751 if(bytesRead != byteSize) 1752 { 1753 if(!in.Rewind()) 1754 { 1755 InitCompressedReading(in, _startPointInMs, _stopPointInMs); 1756 bytesRead = in.Read(outData, byteSize); 1757 if(bytesRead != byteSize) 1758 { 1759 _reading = false; 1760 return -1; 1761 } 1762 } 1763 else 1764 { 1765 _reading = false; 1766 return -1; 1767 } 1768 } 1769 } 1770 #endif 1771 if(bytesRead == 0) 1772 { 1773 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 1774 "ReadCompressedData() no bytes read, codec not supported"); 1775 return -1; 1776 } 1777 1778 _playoutPositionMs += 20; 1779 if((_stopPointInMs > 0) && 1780 (_playoutPositionMs >= _stopPointInMs)) 1781 { 1782 if(!in.Rewind()) 1783 { 1784 InitCompressedReading(in, _startPointInMs, _stopPointInMs); 1785 } 1786 else 1787 { 1788 _reading = false; 1789 } 1790 } 1791 return bytesRead; 1792 } 1793 1794 int32_t ModuleFileUtility::InitCompressedWriting( 1795 OutStream& out, 1796 const CodecInst& codecInst) 1797 { 1798 WEBRTC_TRACE(kTraceDebug, kTraceFile, _id, 1799 "ModuleFileUtility::InitCompressedWriting(out= 0x%x,\ 1800 codecName= %s)", 1801 &out, codecInst.plname); 1802 1803 _writing = false; 1804 1805 #ifdef WEBRTC_CODEC_AMR 1806 if(STR_CASE_CMP(codecInst.plname, "amr") == 0) 1807 { 1808 if(codecInst.pacsize == 160) 1809 { 1810 memcpy(&codec_info_,&codecInst,sizeof(CodecInst)); 1811 _codecId = kCodecAmr; 1812 out.Write("#!AMR\n",6); 1813 _writing = true; 1814 return 0; 1815 } 1816 } 1817 #endif 1818 #ifdef WEBRTC_CODEC_AMRWB 1819 if(STR_CASE_CMP(codecInst.plname, "amr-wb") == 0) 1820 { 1821 if(codecInst.pacsize == 320) 1822 { 1823 memcpy(&codec_info_,&codecInst,sizeof(CodecInst)); 1824 _codecId = kCodecAmrWb; 1825 out.Write("#!AMRWB\n",8); 1826 _writing = true; 1827 return 0; 1828 } 1829 } 1830 #endif 1831 #ifdef WEBRTC_CODEC_ILBC 1832 if(STR_CASE_CMP(codecInst.plname, "ilbc") == 0) 1833 { 1834 if(codecInst.pacsize == 160) 1835 { 1836 _codecId = kCodecIlbc20Ms; 1837 out.Write("#!iLBC20\n",9); 1838 } 1839 else if(codecInst.pacsize == 240) 1840 { 1841 _codecId = kCodecIlbc30Ms; 1842 out.Write("#!iLBC30\n",9); 1843 } 1844 else 1845 { 1846 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 1847 "codecInst defines unsupported compression codec!"); 1848 return -1; 1849 } 1850 memcpy(&codec_info_,&codecInst,sizeof(CodecInst)); 1851 _writing = true; 1852 return 0; 1853 } 1854 #endif 1855 1856 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 1857 "codecInst defines unsupported compression codec!"); 1858 return -1; 1859 } 1860 1861 int32_t ModuleFileUtility::WriteCompressedData( 1862 OutStream& out, 1863 const int8_t* buffer, 1864 const uint32_t dataLength) 1865 { 1866 WEBRTC_TRACE( 1867 kTraceStream, 1868 kTraceFile, 1869 _id, 1870 "ModuleFileUtility::WriteCompressedData(out= 0x%x, buf= 0x%x,\ 1871 dataLen= %d)", 1872 &out, 1873 buffer, 1874 dataLength); 1875 1876 if(buffer == NULL) 1877 { 1878 WEBRTC_TRACE(kTraceError, kTraceFile, _id,"buffer NULL"); 1879 } 1880 1881 if(!out.Write(buffer, dataLength)) 1882 { 1883 return -1; 1884 } 1885 return dataLength; 1886 } 1887 1888 int32_t ModuleFileUtility::InitPCMReading(InStream& pcm, 1889 const uint32_t start, 1890 const uint32_t stop, 1891 uint32_t freq) 1892 { 1893 WEBRTC_TRACE( 1894 kTraceInfo, 1895 kTraceFile, 1896 _id, 1897 "ModuleFileUtility::InitPCMReading(pcm= 0x%x, start=%d, stop=%d,\ 1898 freq=%d)", 1899 &pcm, 1900 start, 1901 stop, 1902 freq); 1903 1904 int8_t dummy[320]; 1905 int32_t read_len; 1906 1907 _playoutPositionMs = 0; 1908 _startPointInMs = start; 1909 _stopPointInMs = stop; 1910 _reading = false; 1911 1912 if(freq == 8000) 1913 { 1914 strcpy(codec_info_.plname, "L16"); 1915 codec_info_.pltype = -1; 1916 codec_info_.plfreq = 8000; 1917 codec_info_.pacsize = 160; 1918 codec_info_.channels = 1; 1919 codec_info_.rate = 128000; 1920 _codecId = kCodecL16_8Khz; 1921 } 1922 else if(freq == 16000) 1923 { 1924 strcpy(codec_info_.plname, "L16"); 1925 codec_info_.pltype = -1; 1926 codec_info_.plfreq = 16000; 1927 codec_info_.pacsize = 320; 1928 codec_info_.channels = 1; 1929 codec_info_.rate = 256000; 1930 _codecId = kCodecL16_16kHz; 1931 } 1932 else if(freq == 32000) 1933 { 1934 strcpy(codec_info_.plname, "L16"); 1935 codec_info_.pltype = -1; 1936 codec_info_.plfreq = 32000; 1937 codec_info_.pacsize = 320; 1938 codec_info_.channels = 1; 1939 codec_info_.rate = 512000; 1940 _codecId = kCodecL16_32Khz; 1941 } 1942 1943 // Readsize for 10ms of audio data (2 bytes per sample). 1944 _readSizeBytes = 2 * codec_info_. plfreq / 100; 1945 if(_startPointInMs > 0) 1946 { 1947 while (_playoutPositionMs < _startPointInMs) 1948 { 1949 read_len = pcm.Read(dummy, _readSizeBytes); 1950 if(read_len == _readSizeBytes) 1951 { 1952 _playoutPositionMs += 10; 1953 } 1954 else // Must have reached EOF before start position! 1955 { 1956 return -1; 1957 } 1958 } 1959 } 1960 _reading = true; 1961 return 0; 1962 } 1963 1964 int32_t ModuleFileUtility::ReadPCMData(InStream& pcm, 1965 int8_t* outData, 1966 uint32_t bufferSize) 1967 { 1968 WEBRTC_TRACE( 1969 kTraceStream, 1970 kTraceFile, 1971 _id, 1972 "ModuleFileUtility::ReadPCMData(pcm= 0x%x, outData= 0x%x, bufSize= %d)", 1973 &pcm, 1974 outData, 1975 bufferSize); 1976 1977 if(outData == NULL) 1978 { 1979 WEBRTC_TRACE(kTraceError, kTraceFile, _id,"buffer NULL"); 1980 } 1981 1982 // Readsize for 10ms of audio data (2 bytes per sample). 1983 uint32_t bytesRequested = 2 * codec_info_.plfreq / 100; 1984 if(bufferSize < bytesRequested) 1985 { 1986 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 1987 "ReadPCMData: buffer not long enough for a 10ms frame."); 1988 assert(false); 1989 return -1; 1990 } 1991 1992 uint32_t bytesRead = pcm.Read(outData, bytesRequested); 1993 if(bytesRead < bytesRequested) 1994 { 1995 if(pcm.Rewind() == -1) 1996 { 1997 _reading = false; 1998 } 1999 else 2000 { 2001 if(InitPCMReading(pcm, _startPointInMs, _stopPointInMs, 2002 codec_info_.plfreq) == -1) 2003 { 2004 _reading = false; 2005 } 2006 else 2007 { 2008 int32_t rest = bytesRequested - bytesRead; 2009 int32_t len = pcm.Read(&(outData[bytesRead]), rest); 2010 if(len == rest) 2011 { 2012 bytesRead += len; 2013 } 2014 else 2015 { 2016 _reading = false; 2017 } 2018 } 2019 if(bytesRead <= 0) 2020 { 2021 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 2022 "ReadPCMData: Failed to rewind audio file."); 2023 return -1; 2024 } 2025 } 2026 } 2027 2028 if(bytesRead <= 0) 2029 { 2030 WEBRTC_TRACE(kTraceStream, kTraceFile, _id, 2031 "ReadPCMData: end of file"); 2032 return -1; 2033 } 2034 _playoutPositionMs += 10; 2035 if(_stopPointInMs && _playoutPositionMs >= _stopPointInMs) 2036 { 2037 if(!pcm.Rewind()) 2038 { 2039 if(InitPCMReading(pcm, _startPointInMs, _stopPointInMs, 2040 codec_info_.plfreq) == -1) 2041 { 2042 _reading = false; 2043 } 2044 } 2045 } 2046 return bytesRead; 2047 } 2048 2049 int32_t ModuleFileUtility::InitPCMWriting(OutStream& out, uint32_t freq) 2050 { 2051 2052 if(freq == 8000) 2053 { 2054 strcpy(codec_info_.plname, "L16"); 2055 codec_info_.pltype = -1; 2056 codec_info_.plfreq = 8000; 2057 codec_info_.pacsize = 160; 2058 codec_info_.channels = 1; 2059 codec_info_.rate = 128000; 2060 2061 _codecId = kCodecL16_8Khz; 2062 } 2063 else if(freq == 16000) 2064 { 2065 strcpy(codec_info_.plname, "L16"); 2066 codec_info_.pltype = -1; 2067 codec_info_.plfreq = 16000; 2068 codec_info_.pacsize = 320; 2069 codec_info_.channels = 1; 2070 codec_info_.rate = 256000; 2071 2072 _codecId = kCodecL16_16kHz; 2073 } 2074 else if(freq == 32000) 2075 { 2076 strcpy(codec_info_.plname, "L16"); 2077 codec_info_.pltype = -1; 2078 codec_info_.plfreq = 32000; 2079 codec_info_.pacsize = 320; 2080 codec_info_.channels = 1; 2081 codec_info_.rate = 512000; 2082 2083 _codecId = kCodecL16_32Khz; 2084 } 2085 if((_codecId != kCodecL16_8Khz) && 2086 (_codecId != kCodecL16_16kHz) && 2087 (_codecId != kCodecL16_32Khz)) 2088 { 2089 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 2090 "CodecInst is not 8KHz PCM or 16KHz PCM!"); 2091 return -1; 2092 } 2093 _writing = true; 2094 _bytesWritten = 0; 2095 return 0; 2096 } 2097 2098 int32_t ModuleFileUtility::WritePCMData(OutStream& out, 2099 const int8_t* buffer, 2100 const uint32_t dataLength) 2101 { 2102 WEBRTC_TRACE( 2103 kTraceStream, 2104 kTraceFile, 2105 _id, 2106 "ModuleFileUtility::WritePCMData(out= 0x%x, buf= 0x%x, dataLen= %d)", 2107 &out, 2108 buffer, 2109 dataLength); 2110 2111 if(buffer == NULL) 2112 { 2113 WEBRTC_TRACE(kTraceError, kTraceFile, _id, "buffer NULL"); 2114 } 2115 2116 if(!out.Write(buffer, dataLength)) 2117 { 2118 return -1; 2119 } 2120 2121 _bytesWritten += dataLength; 2122 return dataLength; 2123 } 2124 2125 int32_t ModuleFileUtility::codec_info(CodecInst& codecInst) 2126 { 2127 WEBRTC_TRACE(kTraceStream, kTraceFile, _id, 2128 "ModuleFileUtility::codec_info(codecInst= 0x%x)", &codecInst); 2129 2130 if(!_reading && !_writing) 2131 { 2132 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 2133 "CodecInst: not currently reading audio file!"); 2134 return -1; 2135 } 2136 memcpy(&codecInst,&codec_info_,sizeof(CodecInst)); 2137 return 0; 2138 } 2139 2140 int32_t ModuleFileUtility::set_codec_info(const CodecInst& codecInst) 2141 { 2142 2143 _codecId = kCodecNoCodec; 2144 if(STR_CASE_CMP(codecInst.plname, "PCMU") == 0) 2145 { 2146 _codecId = kCodecPcmu; 2147 } 2148 else if(STR_CASE_CMP(codecInst.plname, "PCMA") == 0) 2149 { 2150 _codecId = kCodecPcma; 2151 } 2152 else if(STR_CASE_CMP(codecInst.plname, "L16") == 0) 2153 { 2154 if(codecInst.plfreq == 8000) 2155 { 2156 _codecId = kCodecL16_8Khz; 2157 } 2158 else if(codecInst.plfreq == 16000) 2159 { 2160 _codecId = kCodecL16_16kHz; 2161 } 2162 else if(codecInst.plfreq == 32000) 2163 { 2164 _codecId = kCodecL16_32Khz; 2165 } 2166 } 2167 #ifdef WEBRTC_CODEC_AMR 2168 else if(STR_CASE_CMP(codecInst.plname, "amr") == 0) 2169 { 2170 _codecId = kCodecAmr; 2171 } 2172 #endif 2173 #ifdef WEBRTC_CODEC_AMRWB 2174 else if(STR_CASE_CMP(codecInst.plname, "amr-wb") == 0) 2175 { 2176 _codecId = kCodecAmrWb; 2177 } 2178 #endif 2179 #ifdef WEBRTC_CODEC_ILBC 2180 else if(STR_CASE_CMP(codecInst.plname, "ilbc") == 0) 2181 { 2182 if(codecInst.pacsize == 160) 2183 { 2184 _codecId = kCodecIlbc20Ms; 2185 } 2186 else if(codecInst.pacsize == 240) 2187 { 2188 _codecId = kCodecIlbc30Ms; 2189 } 2190 } 2191 #endif 2192 #if(defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) 2193 else if(STR_CASE_CMP(codecInst.plname, "isac") == 0) 2194 { 2195 if(codecInst.plfreq == 16000) 2196 { 2197 _codecId = kCodecIsac; 2198 } 2199 else if(codecInst.plfreq == 32000) 2200 { 2201 _codecId = kCodecIsacSwb; 2202 } 2203 } 2204 #endif 2205 #ifdef WEBRTC_CODEC_ISACLC 2206 else if(STR_CASE_CMP(codecInst.plname, "isaclc") == 0) 2207 { 2208 _codecId = kCodecIsacLc; 2209 } 2210 #endif 2211 #ifdef WEBRTC_CODEC_G722 2212 else if(STR_CASE_CMP(codecInst.plname, "G722") == 0) 2213 { 2214 _codecId = kCodecG722; 2215 } 2216 #endif 2217 else if(STR_CASE_CMP(codecInst.plname, "G7221") == 0) 2218 { 2219 #ifdef WEBRTC_CODEC_G722_1 2220 if(codecInst.plfreq == 16000) 2221 { 2222 if(codecInst.rate == 16000) 2223 { 2224 _codecId = kCodecG722_1_16Kbps; 2225 } 2226 else if(codecInst.rate == 24000) 2227 { 2228 _codecId = kCodecG722_1_24Kbps; 2229 } 2230 else if(codecInst.rate == 32000) 2231 { 2232 _codecId = kCodecG722_1_32Kbps; 2233 } 2234 } 2235 #endif 2236 #ifdef WEBRTC_CODEC_G722_1C 2237 if(codecInst.plfreq == 32000) 2238 { 2239 if(codecInst.rate == 48000) 2240 { 2241 _codecId = kCodecG722_1c_48; 2242 } 2243 else if(codecInst.rate == 32000) 2244 { 2245 _codecId = kCodecG722_1c_32; 2246 } 2247 else if(codecInst.rate == 24000) 2248 { 2249 _codecId = kCodecG722_1c_24; 2250 } 2251 } 2252 #endif 2253 } 2254 #ifdef WEBRTC_CODEC_G726 2255 else if(STR_CASE_CMP(codecInst.plname, "G726-40") == 0) 2256 { 2257 _codecId = kCodecG726_40; 2258 } 2259 else if(STR_CASE_CMP(codecInst.plname, "G726-32") == 0) 2260 { 2261 _codecId = kCodecG726_24; 2262 } 2263 else if(STR_CASE_CMP(codecInst.plname, "G726-24") == 0) 2264 { 2265 _codecId = kCodecG726_32; 2266 } 2267 else if(STR_CASE_CMP(codecInst.plname, "G726-16") == 0) 2268 { 2269 _codecId = kCodecG726_16; 2270 } 2271 #endif 2272 #ifdef WEBRTC_CODEC_G729 2273 else if(STR_CASE_CMP(codecInst.plname, "G729") == 0) 2274 { 2275 _codecId = kCodecG729; 2276 } 2277 #endif 2278 #ifdef WEBRTC_CODEC_G729_1 2279 else if(STR_CASE_CMP(codecInst.plname, "G7291") == 0) 2280 { 2281 _codecId = kCodecG729_1; 2282 } 2283 #endif 2284 #ifdef WEBRTC_CODEC_SPEEX 2285 else if(STR_CASE_CMP(codecInst.plname, "speex") == 0) 2286 { 2287 if(codecInst.plfreq == 8000) 2288 { 2289 _codecId = kCodecSpeex8Khz; 2290 } 2291 else if(codecInst.plfreq == 16000) 2292 { 2293 _codecId = kCodecSpeex16Khz; 2294 } 2295 } 2296 #endif 2297 if(_codecId == kCodecNoCodec) 2298 { 2299 return -1; 2300 } 2301 memcpy(&codec_info_, &codecInst, sizeof(CodecInst)); 2302 return 0; 2303 } 2304 2305 int32_t ModuleFileUtility::FileDurationMs(const char* fileName, 2306 const FileFormats fileFormat, 2307 const uint32_t freqInHz) 2308 { 2309 2310 if(fileName == NULL) 2311 { 2312 WEBRTC_TRACE(kTraceError, kTraceFile, _id, "filename NULL"); 2313 return -1; 2314 } 2315 2316 int32_t time_in_ms = -1; 2317 struct stat file_size; 2318 if(stat(fileName,&file_size) == -1) 2319 { 2320 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 2321 "failed to retrieve file size with stat!"); 2322 return -1; 2323 } 2324 FileWrapper* inStreamObj = FileWrapper::Create(); 2325 if(inStreamObj == NULL) 2326 { 2327 WEBRTC_TRACE(kTraceMemory, kTraceFile, _id, 2328 "failed to create InStream object!"); 2329 return -1; 2330 } 2331 if(inStreamObj->OpenFile(fileName, true) == -1) 2332 { 2333 delete inStreamObj; 2334 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 2335 "failed to open file %s!", fileName); 2336 return -1; 2337 } 2338 2339 switch (fileFormat) 2340 { 2341 case kFileFormatWavFile: 2342 { 2343 if(ReadWavHeader(*inStreamObj) == -1) 2344 { 2345 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 2346 "failed to read WAV file header!"); 2347 return -1; 2348 } 2349 time_in_ms = ((file_size.st_size - 44) / 2350 (_wavFormatObj.nAvgBytesPerSec/1000)); 2351 break; 2352 } 2353 case kFileFormatPcm16kHzFile: 2354 { 2355 // 16 samples per ms. 2 bytes per sample. 2356 int32_t denominator = 16*2; 2357 time_in_ms = (file_size.st_size)/denominator; 2358 break; 2359 } 2360 case kFileFormatPcm8kHzFile: 2361 { 2362 // 8 samples per ms. 2 bytes per sample. 2363 int32_t denominator = 8*2; 2364 time_in_ms = (file_size.st_size)/denominator; 2365 break; 2366 } 2367 case kFileFormatCompressedFile: 2368 { 2369 int32_t cnt = 0; 2370 int32_t read_len = 0; 2371 char buf[64]; 2372 do 2373 { 2374 read_len = inStreamObj->Read(&buf[cnt++], 1); 2375 if(read_len != 1) 2376 { 2377 return -1; 2378 } 2379 } while ((buf[cnt-1] != '\n') && (64 > cnt)); 2380 2381 if(cnt == 64) 2382 { 2383 return -1; 2384 } 2385 else 2386 { 2387 buf[cnt] = 0; 2388 } 2389 #ifdef WEBRTC_CODEC_AMR 2390 if(!strcmp("#!AMR\n", buf)) 2391 { 2392 uint8_t dummy; 2393 read_len = inStreamObj->Read(&dummy, 1); 2394 if(read_len != 1) 2395 { 2396 return -1; 2397 } 2398 2399 int16_t AMRMode = (dummy>>3)&0xF; 2400 2401 // TODO (hellner): use tables instead of hardcoding like this! 2402 // Additionally, this calculation does not 2403 // take octet alignment into consideration. 2404 switch (AMRMode) 2405 { 2406 // Mode 0: 4.75 kbit/sec -> 95 bits per 20 ms frame. 2407 // 20 ms = 95 bits -> 2408 // file size in bytes * 8 / 95 is the number of 2409 // 20 ms frames in the file -> 2410 // time_in_ms = file size * 8 / 95 * 20 2411 case 0: 2412 time_in_ms = ((file_size.st_size)*160)/95; 2413 break; 2414 // Mode 1: 5.15 kbit/sec -> 103 bits per 20 ms frame. 2415 case 1: 2416 time_in_ms = ((file_size.st_size)*160)/103; 2417 break; 2418 // Mode 2: 5.90 kbit/sec -> 118 bits per 20 ms frame. 2419 case 2: 2420 time_in_ms = ((file_size.st_size)*160)/118; 2421 break; 2422 // Mode 3: 6.70 kbit/sec -> 134 bits per 20 ms frame. 2423 case 3: 2424 time_in_ms = ((file_size.st_size)*160)/134; 2425 break; 2426 // Mode 4: 7.40 kbit/sec -> 148 bits per 20 ms frame. 2427 case 4: 2428 time_in_ms = ((file_size.st_size)*160)/148; 2429 break; 2430 // Mode 5: 7.95 bit/sec -> 159 bits per 20 ms frame. 2431 case 5: 2432 time_in_ms = ((file_size.st_size)*160)/159; 2433 break; 2434 // Mode 6: 10.2 bit/sec -> 204 bits per 20 ms frame. 2435 case 6: 2436 time_in_ms = ((file_size.st_size)*160)/204; 2437 break; 2438 // Mode 7: 12.2 bit/sec -> 244 bits per 20 ms frame. 2439 case 7: 2440 time_in_ms = ((file_size.st_size)*160)/244; 2441 break; 2442 // Mode 8: SID Mode -> 39 bits per 20 ms frame. 2443 case 8: 2444 time_in_ms = ((file_size.st_size)*160)/39; 2445 break; 2446 default: 2447 break; 2448 } 2449 } 2450 #endif 2451 #ifdef WEBRTC_CODEC_AMRWB 2452 if(!strcmp("#!AMRWB\n", buf)) 2453 { 2454 uint8_t dummy; 2455 read_len = inStreamObj->Read(&dummy, 1); 2456 if(read_len != 1) 2457 { 2458 return -1; 2459 } 2460 2461 // TODO (hellner): use tables instead of hardcoding like this! 2462 int16_t AMRWBMode = (dummy>>3)&0xF; 2463 switch(AMRWBMode) 2464 { 2465 // Mode 0: 6.6 kbit/sec -> 132 bits per 20 ms frame. 2466 case 0: 2467 time_in_ms = ((file_size.st_size)*160)/132; 2468 break; 2469 // Mode 1: 8.85 kbit/sec -> 177 bits per 20 ms frame. 2470 case 1: 2471 time_in_ms = ((file_size.st_size)*160)/177; 2472 break; 2473 // Mode 2: 12.65 kbit/sec -> 253 bits per 20 ms frame. 2474 case 2: 2475 time_in_ms = ((file_size.st_size)*160)/253; 2476 break; 2477 // Mode 3: 14.25 kbit/sec -> 285 bits per 20 ms frame. 2478 case 3: 2479 time_in_ms = ((file_size.st_size)*160)/285; 2480 break; 2481 // Mode 4: 15.85 kbit/sec -> 317 bits per 20 ms frame. 2482 case 4: 2483 time_in_ms = ((file_size.st_size)*160)/317; 2484 break; 2485 // Mode 5: 18.25 kbit/sec -> 365 bits per 20 ms frame. 2486 case 5: 2487 time_in_ms = ((file_size.st_size)*160)/365; 2488 break; 2489 // Mode 6: 19.85 kbit/sec -> 397 bits per 20 ms frame. 2490 case 6: 2491 time_in_ms = ((file_size.st_size)*160)/397; 2492 break; 2493 // Mode 7: 23.05 kbit/sec -> 461 bits per 20 ms frame. 2494 case 7: 2495 time_in_ms = ((file_size.st_size)*160)/461; 2496 break; 2497 // Mode 8: 23.85 kbit/sec -> 477 bits per 20 ms frame. 2498 case 8: 2499 time_in_ms = ((file_size.st_size)*160)/477; 2500 break; 2501 default: 2502 delete inStreamObj; 2503 return -1; 2504 } 2505 } 2506 #endif 2507 #ifdef WEBRTC_CODEC_ILBC 2508 if(!strcmp("#!iLBC20\n", buf)) 2509 { 2510 // 20 ms is 304 bits 2511 time_in_ms = ((file_size.st_size)*160)/304; 2512 break; 2513 } 2514 if(!strcmp("#!iLBC30\n", buf)) 2515 { 2516 // 30 ms takes 400 bits. 2517 // file size in bytes * 8 / 400 is the number of 2518 // 30 ms frames in the file -> 2519 // time_in_ms = file size * 8 / 400 * 30 2520 time_in_ms = ((file_size.st_size)*240)/400; 2521 break; 2522 } 2523 #endif 2524 break; 2525 } 2526 case kFileFormatPreencodedFile: 2527 { 2528 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 2529 "cannot determine duration of Pre-Encoded file!"); 2530 break; 2531 } 2532 default: 2533 WEBRTC_TRACE(kTraceError, kTraceFile, _id, 2534 "unsupported file format %d!", fileFormat); 2535 break; 2536 } 2537 inStreamObj->CloseFile(); 2538 delete inStreamObj; 2539 return time_in_ms; 2540 } 2541 2542 uint32_t ModuleFileUtility::PlayoutPositionMs() 2543 { 2544 WEBRTC_TRACE(kTraceStream, kTraceFile, _id, 2545 "ModuleFileUtility::PlayoutPosition()"); 2546 2547 if(_reading) 2548 { 2549 return _playoutPositionMs; 2550 } 2551 else 2552 { 2553 return 0; 2554 } 2555 } 2556 } // namespace webrtc 2557