this repo has no description
at fixPythonPipStalling 796 lines 23 kB view raw
1/* 2This file is part of Darling. 3 4Copyright (C) 2020 Lubos Dolezel 5 6Darling is free software: you can redistribute it and/or modify 7it under the terms of the GNU General Public License as published by 8the Free Software Foundation, either version 3 of the License, or 9(at your option) any later version. 10 11Darling is distributed in the hope that it will be useful, 12but WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14GNU General Public License for more details. 15 16You should have received a copy of the GNU General Public License 17along with Darling. If not, see <http://www.gnu.org/licenses/>. 18*/ 19 20#include "AudioConverterImpl.h" 21#include <CarbonCore/MacErrors.h> 22#include <stdexcept> 23#include <cstring> 24#include <cassert> 25#include <iostream> 26#include <sstream> 27#include "stub.h" 28 29extern "C" { 30#include <libavcodec/avcodec.h> 31#include <libavutil/opt.h> 32#include <libavutil/mem.h> 33} 34 35static constexpr int ENCODER_FRAME_SAMPLES = 1024; 36 37// http://blinkingblip.wordpress.com/ 38 39static void throwFFMPEGError(int errnum, const char* function) 40{ 41 char buf[256]; 42 std::stringstream ss; 43 44 if (av_strerror(errnum, buf, sizeof(buf)) == 0) 45 ss << function << ": " << buf; 46 else 47 ss << function << ": unknown error"; 48 49 throw std::runtime_error(ss.str()); 50} 51 52AudioConverter::AudioConverter(const AudioStreamBasicDescription* inSourceFormat, const AudioStreamBasicDescription* inDestinationFormat) 53 : m_sourceFormat(*inSourceFormat), m_destinationFormat(*inDestinationFormat), m_decoder(nullptr), m_encoder(nullptr) 54{ 55 memset(&m_avpkt, 0, sizeof(m_avpkt)); 56 memset(&m_avpktOut, 0, sizeof(m_avpktOut)); 57} 58 59void AudioConverter::flush() 60{ 61 TRACE(); 62 avcodec_flush_buffers(m_decoder); 63 avcodec_flush_buffers(m_encoder); 64 //avcodec_close(m_encoder); 65} 66 67OSStatus AudioConverter::create(const AudioStreamBasicDescription* inSourceFormat, const AudioStreamBasicDescription* inDestinationFormat, AudioConverter** out) 68{ 69 TRACE2(inSourceFormat, inDestinationFormat); 70 71 // TODO: non-interleaved audio 72 73 const AVCodec *codecIn, *codecOut; 74 AVCodecContext *cIn; 75 AVCodecContext *cOut; 76 enum AVCodecID idIn, idOut; 77 78 *out = nullptr; 79 idIn = CACodecToAV(inSourceFormat); 80 idOut = CACodecToAV(inDestinationFormat); 81 82 if (idIn == AV_CODEC_ID_NONE || idOut == AV_CODEC_ID_NONE) 83 { 84 // LOG << "AudioConverter::create(): Unsupported codec, format in = " << std::hex << inSourceFormat->mFormatID << ", out = " << inDestinationFormat->mFormatID << std::dec << std::endl; 85 return paramErr; 86 } 87 88 codecIn = avcodec_find_decoder(idIn); 89 codecOut = avcodec_find_encoder(idOut); 90 91 if (!codecIn || !codecOut) 92 { 93 // LOG << "AudioConverter::create(): avcodec_find_*() failed, format in = " << std::hex << inSourceFormat->mFormatID << ", out = " << inDestinationFormat->mFormatID << std::dec << std::endl; 94 return paramErr; 95 } 96 97 *out = new AudioConverter(inSourceFormat, inDestinationFormat); 98 99 (*out)->m_decoder = cIn = avcodec_alloc_context3(codecIn); 100 101 if (inSourceFormat->mFormatID == kAudioFormatLinearPCM) 102 { 103#warning "TODO: Remove deprecated 'channels' once we no longer support older distros" 104#if LIBAVCODEC_VERSION_MAJOR >= 61 105 cIn->ch_layout.nb_channels = inSourceFormat->mChannelsPerFrame; 106#else 107 cIn->channels = inSourceFormat->mChannelsPerFrame; 108#endif 109 cIn->sample_rate = inSourceFormat->mSampleRate; 110 111#if LIBAVCODEC_VERSION_MAJOR >= 61 112 std::cout << "Converting from PCM with " << cIn->ch_layout.nb_channels << " channels at " << cIn->sample_rate << " Hz\n"; 113#else 114 std::cout << "Converting from PCM with " << cIn->channels << " channels at " << cIn->sample_rate << " Hz\n"; 115#endif 116 } 117 118 if (avcodec_open2((*out)->m_decoder, codecIn, nullptr) < 0) 119 { 120 delete *out; 121 std::cerr << "AudioConverter::create(): avcodec_open() failed, format in = " << std::hex << inSourceFormat->mFormatID << ", out = " << inDestinationFormat->mFormatID << std::dec << std::endl; 122 123 return paramErr; 124 } 125 126 // The encoder will be initialized after we process the first packet 127 (*out)->m_encoder = cOut = avcodec_alloc_context3(codecOut); 128 (*out)->m_codecIn = codecIn; 129 (*out)->m_codecOut = codecOut; 130 131 return noErr; 132} 133 134void AudioConverter::initEncoder() 135{ 136 int err; 137 138 if (m_encoderInitialized) 139 throw std::logic_error("Encoder already initialized"); 140 141 m_encoder->codec_type = AVMEDIA_TYPE_AUDIO; 142 m_encoder->bit_rate = m_outBitRate; 143#warning "TODO: Remove deprecated 'channels' once we no longer support older distros" 144#if LIBAVCODEC_VERSION_MAJOR >= 61 145 m_encoder->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; 146 m_encoder->ch_layout.nb_channels = m_destinationFormat.mChannelsPerFrame; 147#else 148 m_encoder->channels = m_destinationFormat.mChannelsPerFrame; 149 m_encoder->channel_layout = CAChannelCountToLayout(m_destinationFormat.mChannelsPerFrame); 150#endif 151 m_encoder->sample_rate = m_destinationFormat.mSampleRate; 152 m_encoder->sample_fmt = CACodecSampleFormat(&m_destinationFormat); 153 154#ifdef DEBUG_AUDIOCONVERTER 155 std::cout << "ENCODER FORMAT:\n"; 156 std::cout << "\tSample rate: " << m_encoder->sample_rate << std::endl; 157 std::cout << "\tChannels: " << m_destinationFormat.mChannelsPerFrame << std::endl; 158 std::cout << "\tFormat: 0x" << std::hex << m_encoder->sample_fmt << std::dec << std::endl; 159#endif 160 161 err = avcodec_open2(m_encoder, m_codecOut, 0); 162 if (err < 0) 163 throwFFMPEGError(err, "avcodec_open2() encoder"); 164 165 allocateBuffers(); 166 m_encoderInitialized = true; 167} 168 169void AudioConverter::allocateBuffers() 170{ 171#ifdef HAVE_AV_FRAME_ALLOC 172 m_audioFrame = av_frame_alloc(); 173#else 174 m_audioFrame = avcodec_alloc_frame(); 175#endif 176 177 m_audioFrame->nb_samples = ENCODER_FRAME_SAMPLES; 178 m_audioFrame->format = m_encoder->sample_fmt; 179 180#warning "TODO: Remove deprecated 'channels' once we no longer support older distros" 181#if LIBAVCODEC_VERSION_MAJOR >= 61 182 m_audioFrame->ch_layout.order = m_encoder->ch_layout.order; 183 m_audioFrame->ch_layout.nb_channels = m_encoder->ch_layout.nb_channels; 184 int audioSampleBuffer_size = av_samples_get_buffer_size(nullptr, m_encoder->ch_layout.nb_channels, m_audioFrame->nb_samples, m_encoder->sample_fmt, 0); 185#else 186 m_audioFrame->channel_layout = m_encoder->channel_layout; 187 int audioSampleBuffer_size = av_samples_get_buffer_size(nullptr, m_encoder->channels, m_audioFrame->nb_samples, m_encoder->sample_fmt, 0); 188#endif 189 void* audioSampleBuffer = (uint8_t*) av_malloc(audioSampleBuffer_size); 190 191 if (!audioSampleBuffer) 192 { 193 std::cerr << "AudioConverter::allocateBuffers(): Failed to allocate sample buffer\n"; 194 throw std::runtime_error("AudioConverter::allocateBuffers(): Failed to allocate sample buffer"); 195 } 196 197 // Setup the data pointers in the AVFrame 198#if LIBAVCODEC_VERSION_MAJOR >= 61 199 if (int err = avcodec_fill_audio_frame(m_audioFrame, m_encoder->ch_layout.nb_channels, m_encoder->sample_fmt, 200 (const uint8_t*) audioSampleBuffer, audioSampleBuffer_size, 0 ); err < 0) 201#else 202 if (int err = avcodec_fill_audio_frame(m_audioFrame, m_encoder->channels, m_encoder->sample_fmt, 203 (const uint8_t*) audioSampleBuffer, audioSampleBuffer_size, 0 ); err < 0) 204#endif 205 { 206 std::cerr << "AudioConverter::allocateBuffers(): Could not set up audio frame\n"; 207 throw std::runtime_error("AudioConverter::allocateBuffers(): Could not set up audio frame"); 208 } 209} 210 211AudioConverter::~AudioConverter() 212{ 213 TRACE(); 214 if (m_decoder) 215 avcodec_free_context(&m_decoder); 216 if (m_encoder) 217 avcodec_free_context(&m_encoder); 218 if (m_audioFrame) 219 av_free(m_audioFrame); 220 if (m_resampler) 221 swr_free(&m_resampler); 222} 223 224template <typename T> OSStatus setPropertyT(UInt32 inPropertyDataSize, T* localProperty, const void* propertySource) 225{ 226 const T* t = static_cast<const T*>(propertySource); 227 228 if (inPropertyDataSize != sizeof(T)) 229 return kAudioConverterErr_BadPropertySizeError; 230 231 *localProperty = *t; 232 return noErr; 233} 234 235OSStatus AudioConverter::setProperty(AudioConverterPropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData) 236{ 237 switch (inPropertyID) 238 { 239 case kAudioConverterEncodeBitRate: 240 { 241 return setPropertyT(inPropertyDataSize, &m_outBitRate, inPropertyData); 242 } 243 case kAudioConverterInputChannelLayout: 244 { 245 } 246 case kAudioConverterOutputChannelLayout: 247 { 248 } 249 case kAudioConverterCurrentOutputStreamDescription: 250 { 251 return kAudioConverterErr_PropertyNotSupported; 252 //return setPropertyT(inPropertyDataSize, &m_sourceFormat, inPropertyData); 253 } 254 case kAudioConverterCurrentInputStreamDescription: 255 { 256 return kAudioConverterErr_PropertyNotSupported; 257 //return setPropertyT(inPropertyDataSize, &m_destinationFormat, inPropertyData); 258 } 259 default: 260 { 261 STUB(); 262 return kAudioConverterErr_PropertyNotSupported; 263 } 264 } 265 266 return unimpErr; 267} 268 269OSStatus AudioConverter::getPropertyInfo(AudioConverterPropertyID inPropertyID, UInt32 *outSize, Boolean *outWritable) 270{ 271 STUB(); 272 return unimpErr; 273} 274 275template <typename T> OSStatus getPropertyT(UInt32 *ioPropertyDataSize, const T* localProperty, void* propertyTarget) 276{ 277 T* t = static_cast<T*>(propertyTarget); 278 279 if (*ioPropertyDataSize < sizeof(T)) 280 return kAudioConverterErr_BadPropertySizeError; 281 *ioPropertyDataSize = sizeof(T); 282 283 *t = *localProperty; 284 return noErr; 285} 286 287OSStatus AudioConverter::getProperty(AudioConverterPropertyID inPropertyID, UInt32 *ioPropertyDataSize, void *outPropertyData) 288{ 289 switch (inPropertyID) 290 { 291 case kAudioConverterEncodeBitRate: 292 { 293 return getPropertyT(ioPropertyDataSize, &m_outBitRate, outPropertyData); 294 } 295 case kAudioConverterCurrentInputStreamDescription: 296 { 297 return getPropertyT(ioPropertyDataSize, &m_sourceFormat, outPropertyData); 298 } 299 case kAudioConverterCurrentOutputStreamDescription: 300 { 301 return getPropertyT(ioPropertyDataSize, &m_destinationFormat, outPropertyData); 302 } 303 default: 304 { 305 STUB(); 306 return kAudioConverterErr_PropertyNotSupported; 307 } 308 } 309} 310 311OSStatus AudioConverter::feedInput(AudioConverterComplexInputDataProc dataProc, void* opaque, UInt32& numDataPackets) 312{ 313 AudioBufferList bufferList; 314 AudioStreamPacketDescription* aspd; 315 OSStatus err; 316 317 numDataPackets = 4096; // TODO: increase this? 318 bufferList.mNumberBuffers = 1; 319 bufferList.mBuffers[0].mDataByteSize = 0; 320 bufferList.mBuffers[0].mData = nullptr; 321 322 err = dataProc(AudioConverterRef(this), &numDataPackets, &bufferList, &aspd, opaque); 323 324 if (err != noErr) 325 return err; 326 327 m_avpkt.size = bufferList.mBuffers[0].mDataByteSize; 328 m_avpkt.data = (uint8_t*) bufferList.mBuffers[0].mData; 329 330 return noErr; 331} 332 333void AudioConverter::setupResampler(const AVFrame* frame) 334{ 335 int err; 336 337 if (m_resampler != nullptr) 338 throw std::logic_error("Resampler already created"); 339 340 m_resampler = swr_alloc(); 341 m_targetFormat = CACodecSampleFormat(&m_destinationFormat); 342 343 av_opt_set_int(m_resampler, "in_channel_layout", CAChannelCountToLayout(m_sourceFormat.mChannelsPerFrame), 0); 344 av_opt_set_int(m_resampler, "out_channel_layout", CAChannelCountToLayout(m_destinationFormat.mChannelsPerFrame), 0); 345 av_opt_set_int(m_resampler, "in_channels", m_sourceFormat.mChannelsPerFrame, 0); 346 av_opt_set_int(m_resampler, "out_channels", m_destinationFormat.mChannelsPerFrame, 0); 347 av_opt_set_int(m_resampler, "in_sample_rate", frame->sample_rate, 0); 348 av_opt_set_int(m_resampler, "out_sample_rate", m_destinationFormat.mSampleRate, 0); 349 av_opt_set_int(m_resampler, "in_sample_fmt", frame->format, 0); 350 av_opt_set_int(m_resampler, "out_sample_fmt", m_targetFormat, 0); 351 352#ifdef DEBUG_AUDIOCONVERTER 353 std::cout << "RESAMPLER:\n"; 354 std::cout << "\tInput rate: " << frame->sample_rate << std::endl; 355 std::cout << "\tInput format: 0x" << std::hex << frame->format << std::dec <<std::endl; 356 std::cout << "\tOutput rate: " << m_destinationFormat.mSampleRate << std::endl; 357 std::cout << "\tOutput format: 0x" << std::hex << CACodecSampleFormat(&m_destinationFormat) << std::dec << std::endl; 358 359 m_resamplerInput.open("/tmp/resampler.in.raw", std::ios_base::binary | std::ios_base::out); 360 m_resamplerOutput.open("/tmp/resampler.out.raw", std::ios_base::binary | std::ios_base::out); 361 m_encoderOutput.open("/tmp/encoder.out.raw", std::ios_base::binary | std::ios_base::out); 362#endif 363 364 err = swr_init(m_resampler); 365 if (err < 0) 366 throwFFMPEGError(err, "swr_init()"); 367} 368 369OSStatus AudioConverter::fillComplex(AudioConverterComplexInputDataProc dataProc, void* opaque, 370 UInt32* ioOutputDataPacketSize, AudioBufferList *outOutputData, AudioStreamPacketDescription* outPacketDescription) 371{ 372 AVFrame* srcaudio; 373 374#ifdef HAVE_AV_FRAME_ALLOC 375 srcaudio = av_frame_alloc(); 376 av_frame_unref(srcaudio); 377#else 378 srcaudio = avcodec_alloc_frame(); 379 avcodec_get_frame_defaults(srcaudio); 380#endif 381 382 try 383 { 384 for (uint32_t i = 0; i < outOutputData->mNumberBuffers; i++) 385 { 386 UInt32 origSize = outOutputData->mBuffers[i].mDataByteSize; 387 UInt32& newSize = outOutputData->mBuffers[i].mDataByteSize; 388 389 newSize = 0; 390 391 while (newSize < origSize) 392 { 393 if (m_avpktOutUsed < m_avpktOut.size) 394 { 395 // std::cout << "case 1 (used " << m_avpktOutUsed << " from " << m_avpktOut.size << ")\n"; 396 // Feed output from previous conversion 397 while (m_avpktOutUsed < m_avpktOut.size && newSize < origSize) 398 { 399 // Output data 400 int tocopy = std::min<int>(m_avpktOut.size - m_avpktOutUsed, origSize - newSize); 401 memcpy(((char*) outOutputData->mBuffers[i].mData) + newSize, m_avpktOut.data + m_avpktOutUsed, tocopy); 402 newSize += tocopy; 403 m_avpktOutUsed += tocopy; 404 } 405 406 if (m_avpktOutUsed >= m_avpktOut.size) 407 { 408 m_avpktOutUsed = 0; 409 av_packet_unref(&m_avpktOut); 410 } 411 } 412 else 413 { 414 while (!feedEncoder()) 415 { 416 if (!feedDecoder(dataProc, opaque, srcaudio)) 417 goto end; 418 } 419 } 420 } 421 } 422end: 423 424#ifdef HAVE_AV_FRAME_ALLOC 425 av_frame_free(&srcaudio); 426#else 427 avcodec_free_frame(&srcaudio); 428#endif 429 } 430 catch (const std::exception& e) 431 { 432 std::cerr << "AudioConverter::fillComplex(): Exception: " << e.what(); 433#ifdef HAVE_AV_FRAME_ALLOC 434 av_frame_free(&srcaudio); 435#else 436 avcodec_free_frame(&srcaudio); 437#endif 438 return ioErr; 439 } 440 catch (OSStatus err) 441 { 442 std::cerr << "AudioConverter::fillComplex(): OSStatus error: " << err; 443#ifdef HAVE_AV_FRAME_ALLOC 444 av_frame_free(&srcaudio); 445#else 446 avcodec_free_frame(&srcaudio); 447#endif 448 return err; 449 } 450 451 return noErr; 452} 453 454bool AudioConverter::feedDecoder(AudioConverterComplexInputDataProc dataProc, void* opaque, AVFrame* srcaudio) 455{ 456 int gotFrame, err; 457 458 do 459 { 460 // Read input 461 if (!m_avpkt.size) 462 { 463 UInt32 numDataPackets = 0; 464 OSStatus err = feedInput(dataProc, opaque, numDataPackets); 465 466 // The documentation says that this may be a temporary condition 467 if (err != noErr) 468 return false; 469 470 if (!m_avpkt.size) // numDataPackets cannot be trusted 471 return false; 472 } 473 474#if 0 475 err = avcodec_decode_audio4(m_decoder, srcaudio, &gotFrame, &m_avpkt); 476 if (err < 0) 477 throwFFMPEGError(err, "avcodec_decode_audio4()"); 478 479 m_avpkt.size -= err; 480 m_avpkt.data += err; 481#else 482 #warning TODO: test this new avcodec decoder code 483 err = avcodec_send_packet(m_decoder, &m_avpkt); 484 485 if (err < 0) { 486 if (err == AVERROR(EAGAIN)) { 487 // we need to consume frames before sending more packets 488 err = 0; 489 } 490 if (err < 0) { 491 throwFFMPEGError(err, "avcodec_send_packet()"); 492 } 493 } else { 494 // on success, the data packet has been consumed entirely 495 m_avpkt.data += m_avpkt.size; 496 m_avpkt.size = 0; 497 } 498 499 err = avcodec_receive_frame(m_decoder, srcaudio); 500 501 if (err < 0) { 502 gotFrame = false; 503 if (err == AVERROR(EAGAIN)) { 504 // we need to send more packets before consuming a frame 505 err = 0; 506 } 507 if (err < 0) { 508 throwFFMPEGError(err, "avcodec_receive_frame()"); 509 } 510 } else { 511 // on success, we have a valid frame 512 gotFrame = true; 513 } 514#endif 515 516 if (gotFrame) 517 { 518 if (!m_resampler) 519 setupResampler(srcaudio); 520 521#ifdef DEBUG_AUDIOCONVERTER 522 m_resamplerInput.write((char*) srcaudio->data, srcaudio->nb_samples * 2 * m_sourceFormat.mChannelsPerFrame); 523 m_resamplerInput.flush(); 524#endif 525 526 // Resample PCM 527 err = swr_convert(m_resampler, nullptr, 0, (const uint8_t**)&srcaudio->data[0], srcaudio->nb_samples); 528 if (err < 0) 529 throwFFMPEGError(err, "swr_convert()"); 530 } 531 } 532 while (!gotFrame); 533 534 return true; 535} 536 537bool AudioConverter::feedEncoder() 538{ 539 int gotFrame = 0, err; 540 uint8_t *output; 541 int out_linesize; 542 int avail; 543 544 if (!m_resampler) 545 return false; 546 547 if (!m_encoderInitialized) 548 initEncoder(); 549 550 assert(m_avpktOutUsed == m_avpktOut.size); 551 552 const size_t bytesPerSample = m_destinationFormat.mBitsPerChannel / 8; 553 const size_t bytesPerFrame = m_destinationFormat.mChannelsPerFrame * bytesPerSample; 554 const size_t requiredBytes = bytesPerFrame * ENCODER_FRAME_SAMPLES; 555 556 while (m_audioFramePrebuf.size() < requiredBytes && (avail = swr_get_out_samples(m_resampler, 0)) > 0) 557 { 558 av_samples_alloc(&output, &out_linesize, m_destinationFormat.mChannelsPerFrame, 559 avail, m_encoder->sample_fmt, 0); 560 561 if ((avail = swr_convert(m_resampler, &output, avail, nullptr, 0)) < 0) 562 { 563 av_freep(&output); 564 throwFFMPEGError(err, "swr_convert()"); 565 } 566 567#ifdef DEBUG_AUDIOCONVERTER 568 m_resamplerOutput.write((char*) output, avail * bytesPerFrame); 569 m_resamplerOutput.flush(); 570#endif 571 572 m_audioFramePrebuf.push(output, avail * bytesPerFrame); 573 av_freep(&output); 574 } 575 576 av_init_packet(&m_avpktOut); 577 m_avpktOut.data = 0; 578 m_avpktOut.size = 0; 579 m_avpktOutUsed = 0; 580 581 if (m_audioFramePrebuf.size() >= requiredBytes) 582 { 583 try 584 { 585 err = avcodec_fill_audio_frame(m_audioFrame, m_destinationFormat.mChannelsPerFrame, 586 m_targetFormat, m_audioFramePrebuf.data(), requiredBytes, 0); 587 588 if (err < 0) 589 throwFFMPEGError(err, "avcodec_fill_audio_frame()"); 590 591#if 0 592 err = avcodec_encode_audio2(m_encoder, &m_avpktOut, m_audioFrame, &gotFrame); 593 if (err < 0) 594 throwFFMPEGError(err, "avcodec_encode_audio2()"); 595#else 596 #warning TODO: test this new avcodec encoder code 597 err = avcodec_send_frame(m_encoder, m_audioFrame); 598 599 if (err < 0) { 600 if (err == AVERROR(EAGAIN)) { 601 // we need to consume more packets before sending 602 // TODO: handle this case properly. 603 // for now, we just proceed to throw an error to avoid dropping a frame 604 } 605 if (err < 0) { 606 throwFFMPEGError(err, "avcodec_send_frame()"); 607 } 608 } 609 610 err = avcodec_receive_packet(m_encoder, &m_avpkt); 611 612 if (err < 0) { 613 gotFrame = false; 614 if (err == AVERROR(EAGAIN)) { 615 // we need to send more frames before consuming a packet 616 err = 0; 617 } 618 if (err < 0) { 619 throwFFMPEGError(err, "avcodec_receive_packet()"); 620 } 621 } else { 622 gotFrame = true; 623 } 624#endif 625 626 m_audioFramePrebuf.consume(requiredBytes); 627 628#ifdef DEBUG_AUDIOCONVERTER 629 if (gotFrame) 630 m_encoderOutput.write((char*) m_avpktOut.data, m_avpktOut.size); 631#endif 632 } 633 catch (...) 634 { 635 m_audioFramePrebuf.consume(requiredBytes); 636 throw; 637 } 638 639 return gotFrame; 640 } 641 return false; 642} 643 644uint32_t AudioConverter::CAChannelCountToLayout(UInt32 numChannels) 645{ 646 // TODO: this is just wild guessing 647 switch (numChannels) 648 { 649 case 1: 650 return AV_CH_LAYOUT_MONO; 651 case 2: 652 return AV_CH_LAYOUT_STEREO; 653 case 3: 654 return AV_CH_LAYOUT_SURROUND; 655 case 4: 656 return AV_CH_LAYOUT_4POINT0; 657 case 5: 658 return AV_CH_LAYOUT_4POINT1; 659 case 6: 660 return AV_CH_LAYOUT_5POINT1; 661 case 7: 662 return AV_CH_LAYOUT_6POINT1; 663 case 8: 664 return AV_CH_LAYOUT_7POINT1; 665 default: 666 return AV_CH_LAYOUT_STEREO; 667 } 668} 669 670enum AVSampleFormat AudioConverter::CACodecSampleFormat(const AudioStreamBasicDescription* desc) 671{ 672 if (desc->mFormatFlags & kAudioFormatFlagIsFloat) 673 { 674 if (desc->mBitsPerChannel == 32) 675 return AV_SAMPLE_FMT_FLT; 676 else if (desc->mBitsPerChannel == 64) 677 return AV_SAMPLE_FMT_DBL; 678 else 679 return AV_SAMPLE_FMT_NONE; 680 } 681 else 682 { 683 684 switch (desc->mBitsPerChannel) 685 { 686 case 8: return AV_SAMPLE_FMT_U8; 687 case 16: return AV_SAMPLE_FMT_S16; 688 case 24: return AV_SAMPLE_FMT_S32; // FIXME: 24-bits? 689 case 32: return AV_SAMPLE_FMT_S32; 690 default: return AV_SAMPLE_FMT_NONE; 691 } 692 } 693} 694 695enum AVCodecID AudioConverter::CACodecToAV(const AudioStreamBasicDescription* desc) 696{ 697 switch (desc->mFormatID) 698 { 699 case kAudioFormatLinearPCM: 700 { 701 if (desc->mFormatFlags & kAudioFormatFlagIsFloat) 702 { 703 if (desc->mFormatFlags & kAudioFormatFlagIsBigEndian) 704 { 705 if (desc->mBitsPerChannel == 32) 706 return AV_CODEC_ID_PCM_F32BE; 707 else if (desc->mBitsPerChannel == 64) 708 return AV_CODEC_ID_PCM_F64BE; 709 } 710 else 711 { 712 if (desc->mBitsPerChannel == 32) 713 return AV_CODEC_ID_PCM_F32LE; 714 else if (desc->mBitsPerChannel == 64) 715 return AV_CODEC_ID_PCM_F64LE; 716 } 717 } 718 else if (desc->mFormatFlags & kAudioFormatFlagIsSignedInteger) 719 { 720 enum AVCodecID cid; 721 722 switch (desc->mBitsPerChannel) 723 { 724 case 8: cid = AV_CODEC_ID_PCM_S8; break; 725 case 16: cid = AV_CODEC_ID_PCM_S16LE; break; 726 case 24: cid = AV_CODEC_ID_PCM_S24LE; break; 727 case 32: cid = AV_CODEC_ID_PCM_S32LE; break; 728 default: return AV_CODEC_ID_NONE; 729 } 730 731 if (desc->mBitsPerChannel != 8 && desc->mFormatFlags & kAudioFormatFlagIsBigEndian) 732 cid = (enum AVCodecID)(int(cid)+1); 733 return cid; 734 } 735 else 736 { 737 enum AVCodecID cid; 738 739 switch (desc->mBitsPerChannel) 740 { 741 case 8: cid = AV_CODEC_ID_PCM_U8; break; 742 case 16: cid = AV_CODEC_ID_PCM_U16LE; break; 743 case 24: cid = AV_CODEC_ID_PCM_U24LE; break; 744 case 32: cid = AV_CODEC_ID_PCM_U32LE; break; 745 default: return AV_CODEC_ID_NONE; 746 } 747 748 if (desc->mBitsPerChannel != 8 && desc->mFormatFlags & kAudioFormatFlagIsBigEndian) 749 cid = (enum AVCodecID)(int(cid)+1); 750 return cid; 751 } 752 return AV_CODEC_ID_NONE; 753 } 754 case kAudioFormatULaw: 755 return AV_CODEC_ID_PCM_MULAW; 756 case kAudioFormatALaw: 757 return AV_CODEC_ID_PCM_ALAW; 758 case kAudioFormatMPEGLayer1: 759 return AV_CODEC_ID_MP1; 760 case kAudioFormatMPEGLayer2: 761 return AV_CODEC_ID_MP2; 762 case kAudioFormatMPEGLayer3: 763 return AV_CODEC_ID_MP3; 764 case kAudioFormatAC3: 765 case kAudioFormat60958AC3: // TODO: is this correct? 766 return AV_CODEC_ID_AC3; 767 case kAudioFormatAppleIMA4: 768 return AV_CODEC_ID_ADPCM_IMA_DK4; // TODO: is this correct? 769 case kAudioFormatMPEG4AAC: 770 case kAudioFormatMPEG4AAC_HE: 771 case kAudioFormatMPEG4AAC_LD: 772 case kAudioFormatMPEG4AAC_ELD: 773 case kAudioFormatMPEG4AAC_ELD_SBR: 774 case kAudioFormatMPEG4AAC_ELD_V2: 775 case kAudioFormatMPEG4AAC_HE_V2: 776 case kAudioFormatMPEG4AAC_Spatial: 777 return AV_CODEC_ID_AAC; 778 case kAudioFormatMPEG4CELP: 779 return AV_CODEC_ID_QCELP; // TODO: is this correct? 780 case kAudioFormatAMR: 781 return AV_CODEC_ID_AMR_NB; 782 case kAudioFormatiLBC: 783 return AV_CODEC_ID_ILBC; 784 case kAudioFormatAppleLossless: 785 return AV_CODEC_ID_APE; 786 case kAudioFormatMicrosoftGSM: 787 return AV_CODEC_ID_GSM_MS; 788 case kAudioFormatMACE3: 789 return AV_CODEC_ID_MACE3; 790 case kAudioFormatMACE6: 791 return AV_CODEC_ID_MACE6; 792 default: 793 return AV_CODEC_ID_NONE; 794 } 795} 796