Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/cast/sender/audio_encoder.h" | 5 #include "media/cast/sender/audio_encoder.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 11 #include "base/location.h" | 11 #include "base/location.h" |
| 12 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
| 13 #include "base/sys_byteorder.h" | 13 #include "base/sys_byteorder.h" |
| 14 #include "base/time/time.h" | 14 #include "base/time/time.h" |
| 15 #include "media/base/audio_bus.h" | 15 #include "media/base/audio_bus.h" |
| 16 #include "media/cast/cast_defines.h" | 16 #include "media/cast/cast_defines.h" |
| 17 #include "media/cast/cast_environment.h" | 17 #include "media/cast/cast_environment.h" |
| 18 | |
| 19 #if !defined(OS_IOS) | |
| 18 #include "third_party/opus/src/include/opus.h" | 20 #include "third_party/opus/src/include/opus.h" |
| 21 #endif | |
| 22 | |
| 23 #if defined(OS_MACOSX) | |
| 24 #include <AudioToolbox/AudioToolbox.h> | |
| 25 #endif | |
| 19 | 26 |
| 20 namespace media { | 27 namespace media { |
| 21 namespace cast { | 28 namespace cast { |
| 22 | 29 |
| 23 | 30 |
| 24 // Base class that handles the common problem of feeding one or more AudioBus' | 31 // Base class that handles the common problem of feeding one or more AudioBus' |
| 25 // data into a buffer and then, once the buffer is full, encoding the signal and | 32 // data into a buffer and then, once the buffer is full, encoding the signal and |
| 26 // emitting an EncodedFrame via the FrameEncodedCallback. | 33 // emitting an EncodedFrame via the FrameEncodedCallback. |
| 27 // | 34 // |
| 28 // Subclasses complete the implementation by handling the actual encoding | 35 // Subclasses complete the implementation by handling the actual encoding |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 192 // the RTP timestamps. | 199 // the RTP timestamps. |
| 193 base::TimeTicks frame_capture_time_; | 200 base::TimeTicks frame_capture_time_; |
| 194 | 201 |
| 195 // Set to non-zero to indicate the next output frame skipped over audio | 202 // Set to non-zero to indicate the next output frame skipped over audio |
| 196 // samples in order to recover from an input underrun. | 203 // samples in order to recover from an input underrun. |
| 197 int samples_dropped_from_buffer_; | 204 int samples_dropped_from_buffer_; |
| 198 | 205 |
| 199 DISALLOW_COPY_AND_ASSIGN(ImplBase); | 206 DISALLOW_COPY_AND_ASSIGN(ImplBase); |
| 200 }; | 207 }; |
| 201 | 208 |
| 209 #if !defined(OS_IOS) | |
| 202 class AudioEncoder::OpusImpl : public AudioEncoder::ImplBase { | 210 class AudioEncoder::OpusImpl : public AudioEncoder::ImplBase { |
| 203 public: | 211 public: |
| 204 OpusImpl(const scoped_refptr<CastEnvironment>& cast_environment, | 212 OpusImpl(const scoped_refptr<CastEnvironment>& cast_environment, |
| 205 int num_channels, | 213 int num_channels, |
| 206 int sampling_rate, | 214 int sampling_rate, |
| 207 int bitrate, | 215 int bitrate, |
| 208 const FrameEncodedCallback& callback) | 216 const FrameEncodedCallback& callback) |
| 209 : ImplBase(cast_environment, | 217 : ImplBase(cast_environment, |
| 210 CODEC_AUDIO_OPUS, | 218 CODEC_AUDIO_OPUS, |
| 211 num_channels, | 219 num_channels, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 283 // This is the recommended value, according to documentation in | 291 // This is the recommended value, according to documentation in |
| 284 // third_party/opus/src/include/opus.h, so that the Opus encoder does not | 292 // third_party/opus/src/include/opus.h, so that the Opus encoder does not |
| 285 // degrade the audio due to memory constraints. | 293 // degrade the audio due to memory constraints. |
| 286 // | 294 // |
| 287 // Note: Whereas other RTP implementations do not, the cast library is | 295 // Note: Whereas other RTP implementations do not, the cast library is |
| 288 // perfectly capable of transporting larger than MTU-sized audio frames. | 296 // perfectly capable of transporting larger than MTU-sized audio frames. |
| 289 static const int kOpusMaxPayloadSize = 4000; | 297 static const int kOpusMaxPayloadSize = 4000; |
| 290 | 298 |
| 291 DISALLOW_COPY_AND_ASSIGN(OpusImpl); | 299 DISALLOW_COPY_AND_ASSIGN(OpusImpl); |
| 292 }; | 300 }; |
| 301 #endif | |
| 302 | |
| 303 #if defined(OS_MACOSX) | |
| 304 class AudioEncoder::AacAudioConverterImpl : public AudioEncoder::ImplBase { | |
| 305 public: | |
| 306 AacAudioConverterImpl(const scoped_refptr<CastEnvironment>& cast_environment, | |
| 307 int num_channels, | |
| 308 int sampling_rate, | |
| 309 int bitrate, | |
| 310 const FrameEncodedCallback& callback) | |
| 311 : ImplBase(cast_environment, | |
| 312 CODEC_AUDIO_AAC, | |
| 313 num_channels, | |
| 314 sampling_rate, | |
| 315 1024, /* AudioConverter produces 1024 samples blocks */ | |
|
miu
2014/09/29 19:54:47
s/AudioConverter/AacImpl/
| |
| 316 callback), | |
| 317 input_buffer_(AudioBus::Create(num_channels, 1024)), | |
| 318 output_buffer_(nullptr), | |
| 319 converter_(nullptr), | |
| 320 file_(nullptr), | |
| 321 num_encoded_packets_(0), | |
| 322 max_packet_size_(0), | |
| 323 can_resume_(true) { | |
| 324 if (ImplBase::cast_initialization_status_ != STATUS_AUDIO_UNINITIALIZED) { | |
| 325 return; | |
| 326 } | |
| 327 if (!Initialize(sampling_rate, bitrate)) { | |
| 328 ImplBase::cast_initialization_status_ = | |
| 329 STATUS_INVALID_AUDIO_CONFIGURATION; | |
| 330 return; | |
| 331 } | |
| 332 ImplBase::cast_initialization_status_ = STATUS_AUDIO_INITIALIZED; | |
| 333 } | |
| 334 | |
| 335 private: | |
| 336 // The |AudioConverterFillComplexBuffer| input callback function. Returns the | |
| 337 // data that has been copied into the encoder's |buffer_| by the | |
| 338 // |TransferSamplesIntoBuffer| method. | |
|
miu
2014/09/29 19:54:47
Just a sanity-check: This callback is called synch
jfroy
2014/10/14 01:06:34
Yep. I'll add the comment.
| |
| 339 static OSStatus ConverterFillDataCallback( | |
|
miu
2014/09/29 19:54:47
style nit: static methods need to be declared/defi
| |
| 340 AudioConverterRef in_converter, | |
| 341 UInt32* io_num_packets, | |
| 342 AudioBufferList* io_data, | |
| 343 AudioStreamPacketDescription** out_packet_desc, | |
| 344 void* in_encoder) { | |
| 345 DCHECK(io_data); | |
| 346 DCHECK(in_encoder); | |
| 347 auto encoder = reinterpret_cast<const AacAudioConverterImpl*>(in_encoder); | |
| 348 | |
| 349 // Provide the entire content of the input buffer. | |
| 350 const int num_frames = encoder->input_buffer_->frames(); | |
| 351 *io_num_packets = num_frames; | |
| 352 | |
| 353 DCHECK_EQ(io_data->mNumberBuffers, | |
| 354 static_cast<unsigned>(encoder->input_buffer_->channels())); | |
| 355 for (int i_buf = 0, end = io_data->mNumberBuffers; i_buf < end; ++i_buf) { | |
| 356 io_data->mBuffers[i_buf].mNumberChannels = 1; | |
| 357 io_data->mBuffers[i_buf].mDataByteSize = sizeof(float) * num_frames; | |
| 358 io_data->mBuffers[i_buf].mData = encoder->input_buffer_->channel(i_buf); | |
| 359 } | |
| 360 return noErr; | |
| 361 } | |
| 362 | |
| 363 // The AudioFile write callback function. Appends the data to the encoder's | |
| 364 // current output buffer. | |
| 365 static OSStatus FileWriteCallback(void* in_encoder, | |
| 366 SInt64 in_position, | |
| 367 UInt32 in_size, | |
| 368 const void* in_buffer, | |
| 369 UInt32* out_size) { | |
| 370 DCHECK(in_encoder); | |
| 371 auto encoder = reinterpret_cast<const AacAudioConverterImpl*>(in_encoder); | |
| 372 DCHECK(in_buffer); | |
| 373 auto buffer = reinterpret_cast<const std::string::value_type*>(in_buffer); | |
| 374 | |
| 375 std::string* const output_buffer = encoder->output_buffer_; | |
| 376 DCHECK(output_buffer); | |
| 377 | |
| 378 output_buffer->append(buffer, in_size); | |
| 379 *out_size = in_size; | |
| 380 return noErr; | |
| 381 } | |
| 382 | |
| 383 virtual ~AacAudioConverterImpl() { Teardown(); } | |
| 384 | |
| 385 // Destroys the existing audio converter and file, if any. | |
| 386 void Teardown() { | |
| 387 if (converter_) { | |
| 388 AudioConverterDispose(converter_); | |
| 389 converter_ = nullptr; | |
| 390 } | |
| 391 if (file_) { | |
| 392 AudioFileClose(file_); | |
| 393 file_ = nullptr; | |
| 394 } | |
| 395 } | |
| 396 | |
| 397 // Initializes the audio converter and file. Calls Teardown to destroy any | |
| 398 // existing state. This is so that Initialize() may be called to setup another | |
| 399 // converter after a non-resumable interruption. | |
| 400 bool Initialize(int sampling_rate, int bitrate) { | |
| 401 // Teardown previous audio converter and file. | |
| 402 Teardown(); | |
| 403 | |
| 404 // Input data comes from AudioBus objects, which carry deinterleaved packed | |
| 405 // native-endian float samples. | |
| 406 AudioStreamBasicDescription in_asbd; | |
| 407 in_asbd.mSampleRate = sampling_rate; | |
| 408 in_asbd.mFormatID = kAudioFormatLinearPCM; | |
| 409 in_asbd.mFormatFlags = | |
| 410 kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved; | |
| 411 in_asbd.mChannelsPerFrame = num_channels_; | |
| 412 in_asbd.mBitsPerChannel = sizeof(float) * 8; | |
| 413 in_asbd.mFramesPerPacket = 1; | |
| 414 in_asbd.mBytesPerPacket = in_asbd.mBytesPerFrame = sizeof(float); | |
|
miu
2014/09/29 19:54:47
Somehow, this doesn't seem right. Only 4 bytes pe
jfroy
2014/10/14 01:06:34
In Core Audio, a frame of audio is one sample acro
| |
| 415 in_asbd.mReserved = 0; | |
| 416 | |
| 417 // Request AAC-LC encoding, with no downmixing or downsampling. | |
| 418 AudioStreamBasicDescription out_asbd; | |
| 419 memset(&out_asbd, 0, sizeof(AudioStreamBasicDescription)); | |
| 420 out_asbd.mSampleRate = sampling_rate; | |
| 421 out_asbd.mFormatID = kAudioFormatMPEG4AAC; | |
| 422 out_asbd.mChannelsPerFrame = num_channels_; | |
| 423 UInt32 prop_size = sizeof(out_asbd); | |
| 424 if (AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, | |
| 425 0, | |
| 426 nullptr, | |
| 427 &prop_size, | |
| 428 &out_asbd) != noErr) { | |
| 429 return false; | |
| 430 } | |
| 431 | |
| 432 if (AudioConverterNew(&in_asbd, &out_asbd, &converter_) != noErr) { | |
| 433 return false; | |
| 434 } | |
| 435 | |
| 436 // The converter is allowed to modify (really fill-in) the output format. | |
| 437 // After creation, we can query the final output format. | |
| 438 prop_size = sizeof(out_asbd); | |
| 439 if (AudioConverterGetProperty(converter_, | |
| 440 kAudioConverterCurrentOutputStreamDescription, | |
| 441 &prop_size, | |
| 442 &out_asbd) != noErr) { | |
| 443 return false; | |
| 444 } | |
| 445 | |
| 446 // If bitrate is <= 0, allow the encoder to pick a suitable value. | |
| 447 // Otherwise, set the bitrate (which can fail if the value is not suitable | |
| 448 // or compatible with the output sampling rate or channels). | |
| 449 if (bitrate > 0) { | |
| 450 prop_size = sizeof(int); | |
| 451 if (AudioConverterSetProperty( | |
| 452 converter_, kAudioConverterEncodeBitRate, prop_size, &bitrate) != | |
| 453 noErr) { | |
| 454 return false; | |
| 455 } | |
| 456 } | |
| 457 | |
| 458 // See the comment next to |can_resume_| for details on resumption. Some | |
| 459 // converters can return kAudioConverterErr_PropertyNotSupported, in which | |
| 460 // case resumption is implicitly supported. | |
| 461 uint32_t can_resume; | |
| 462 prop_size = sizeof(can_resume); | |
| 463 OSStatus oserr = AudioConverterGetProperty( | |
| 464 converter_, | |
| 465 kAudioConverterPropertyCanResumeFromInterruption, | |
| 466 &prop_size, | |
| 467 &can_resume); | |
| 468 if (oserr == noErr) { | |
| 469 const_cast<bool&>(can_resume_) = can_resume != 0; | |
| 470 } | |
| 471 | |
| 472 // mBytesPerPacket will be 0 for variable packet size configurations, in | |
| 473 // which case we must query the maximum possible packet size. | |
| 474 const_cast<uint32_t&>(max_packet_size_) = out_asbd.mBytesPerPacket; | |
| 475 if (max_packet_size_ == 0) { | |
| 476 prop_size = sizeof(max_packet_size_); | |
| 477 if (AudioConverterGetProperty( | |
| 478 converter_, | |
| 479 kAudioConverterPropertyMaximumOutputPacketSize, | |
| 480 &prop_size, | |
| 481 const_cast<uint32_t*>(&max_packet_size_)) != noErr) { | |
| 482 return false; | |
| 483 } | |
| 484 } | |
| 485 | |
| 486 // This is the only location where we modify the packet buffer. | |
| 487 const_cast<scoped_ptr<uint8[]>&>(packet_buffer_) | |
| 488 .reset(new uint8[max_packet_size_]); | |
| 489 | |
| 490 // The "magic cookie" is an encoder state vector required for decoding and | |
| 491 // packing. We query it from the converter and set it on the file below. | |
| 492 UInt32 cookie_size; | |
| 493 if (AudioConverterGetPropertyInfo(converter_, | |
| 494 kAudioConverterCompressionMagicCookie, | |
| 495 &cookie_size, | |
| 496 nullptr) != noErr) { | |
| 497 return false; | |
| 498 } | |
| 499 scoped_ptr<int8[]> cookie_data(new int8[cookie_size]); | |
|
miu
2014/09/29 19:54:47
Sanity-check: Did you mean uint8 here, or is int8
jfroy
2014/10/14 01:06:34
Their API use void*, which doesn't play well in C+
| |
| 500 if (AudioConverterGetProperty(converter_, | |
| 501 kAudioConverterCompressionMagicCookie, | |
| 502 &cookie_size, | |
| 503 cookie_data.get()) != noErr) { | |
| 504 return false; | |
| 505 } | |
| 506 | |
| 507 if (AudioFileInitializeWithCallbacks(this, | |
| 508 nullptr, | |
| 509 &FileWriteCallback, | |
| 510 nullptr, | |
| 511 nullptr, | |
| 512 kAudioFileAAC_ADTSType, | |
| 513 &out_asbd, | |
| 514 0, | |
| 515 &file_) != noErr) { | |
| 516 return false; | |
| 517 } | |
| 518 | |
| 519 if (AudioFileSetProperty(file_, | |
| 520 kAudioFilePropertyMagicCookieData, | |
| 521 cookie_size, | |
| 522 cookie_data.get()) != noErr) { | |
| 523 return false; | |
| 524 } | |
| 525 | |
| 526 return true; | |
| 527 } | |
| 528 | |
| 529 virtual void TransferSamplesIntoBuffer(const AudioBus* audio_bus, | |
| 530 int source_offset, | |
| 531 int buffer_fill_offset, | |
| 532 int num_samples) override { | |
| 533 audio_bus->CopyPartialFramesTo( | |
| 534 source_offset, num_samples, buffer_fill_offset, input_buffer_.get()); | |
| 535 } | |
| 536 | |
| 537 virtual bool EncodeFromFilledBuffer(std::string* out) override { | |
| 538 AudioBufferList out_abl; | |
|
miu
2014/09/29 19:54:47
nit: Can out_abl be initialized once in Initialize
jfroy
2014/10/14 01:06:34
Good idea.
| |
| 539 out_abl.mNumberBuffers = 1; | |
| 540 out_abl.mBuffers[0].mNumberChannels = num_channels_; | |
| 541 out_abl.mBuffers[0].mDataByteSize = max_packet_size_; | |
| 542 out_abl.mBuffers[0].mData = packet_buffer_.get(); | |
| 543 | |
| 544 UInt32 io_num_packets = 1; | |
| 545 AudioStreamPacketDescription packet_description; | |
| 546 if (AudioConverterFillComplexBuffer(converter_, | |
| 547 &ConverterFillDataCallback, | |
| 548 this, | |
| 549 &io_num_packets, | |
| 550 &out_abl, | |
| 551 &packet_description) != noErr || | |
| 552 io_num_packets == 0) { | |
| 553 return false; | |
| 554 } | |
| 555 | |
| 556 // Reserve enough space to write the packet and a basic ADTS header. | |
| 557 out->reserve(packet_description.mDataByteSize + 7); | |
|
miu
2014/09/29 19:54:47
Where does 7 come from? Can you specify this as s
jfroy
2014/10/14 01:06:34
It's the ADTS header size. I've switched to a cons
| |
| 558 | |
| 559 output_buffer_ = out; | |
| 560 OSStatus oserr = AudioFileWritePackets(file_, | |
| 561 false, | |
| 562 out_abl.mBuffers[0].mDataByteSize, | |
| 563 &packet_description, | |
| 564 num_encoded_packets_, | |
| 565 &io_num_packets, | |
| 566 out_abl.mBuffers[0].mData); | |
| 567 output_buffer_ = nullptr; | |
| 568 if (oserr != noErr || io_num_packets == 0) { | |
| 569 return false; | |
| 570 } | |
| 571 num_encoded_packets_ += io_num_packets; | |
| 572 return true; | |
| 573 } | |
| 574 | |
| 575 // A buffer that holds one encoded packet worth of audio frames. Initialized | |
| 576 // during construction. | |
| 577 const scoped_ptr<AudioBus> input_buffer_; | |
| 578 | |
| 579 // A buffer that holds one encoded packet. Initialized in |Initialize| once | |
| 580 // the maximum packet size is known. | |
| 581 const scoped_ptr<uint8[]> packet_buffer_; | |
| 582 | |
| 583 // A temporary pointer to the current output buffer. Only non-null when | |
| 584 // writing a packet for use by the AudioFile write callback. | |
| 585 std::string* output_buffer_; | |
| 586 | |
| 587 // The AudioConverter is responsible for encoding LPCM frames to AAC packets. | |
| 588 AudioConverterRef converter_; | |
| 589 | |
| 590 // The AudioFile is responsible for wrapping AAC packets into ADTS packets. | |
| 591 AudioFileID file_; | |
| 592 | |
| 593 // The number of encoded packets emitted so far by the encoder. | |
| 594 uint64_t num_encoded_packets_; | |
| 595 | |
| 596 // The maximum packet size that the encoder can emit. | |
| 597 const uint32_t max_packet_size_; | |
| 598 | |
| 599 // On iOS, AudioConverter can be interrupted by other services (such as an | |
| 600 // audio alert or phone call). Depending on the underlying hardware and | |
| 601 // configuration, the converter may have to be thrown away and re-initialized | |
| 602 // after such an interruption. This flag tracks if we can resume or not. | |
| 603 const bool can_resume_; | |
|
miu
2014/09/29 19:54:47
Is this used anywhere?
jfroy
2014/10/14 01:06:34
Not yet but I'll be filing a bug to add support fo
| |
| 604 | |
| 605 DISALLOW_COPY_AND_ASSIGN(AacAudioConverterImpl); | |
| 606 }; | |
| 607 #endif // defined(OS_MACOSX) | |
| 293 | 608 |
| 294 class AudioEncoder::Pcm16Impl : public AudioEncoder::ImplBase { | 609 class AudioEncoder::Pcm16Impl : public AudioEncoder::ImplBase { |
| 295 public: | 610 public: |
| 296 Pcm16Impl(const scoped_refptr<CastEnvironment>& cast_environment, | 611 Pcm16Impl(const scoped_refptr<CastEnvironment>& cast_environment, |
| 297 int num_channels, | 612 int num_channels, |
| 298 int sampling_rate, | 613 int sampling_rate, |
| 299 const FrameEncodedCallback& callback) | 614 const FrameEncodedCallback& callback) |
| 300 : ImplBase(cast_environment, | 615 : ImplBase(cast_environment, |
| 301 CODEC_AUDIO_PCM16, | 616 CODEC_AUDIO_PCM16, |
| 302 num_channels, | 617 num_channels, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 345 int num_channels, | 660 int num_channels, |
| 346 int sampling_rate, | 661 int sampling_rate, |
| 347 int bitrate, | 662 int bitrate, |
| 348 Codec codec, | 663 Codec codec, |
| 349 const FrameEncodedCallback& frame_encoded_callback) | 664 const FrameEncodedCallback& frame_encoded_callback) |
| 350 : cast_environment_(cast_environment) { | 665 : cast_environment_(cast_environment) { |
| 351 // Note: It doesn't matter which thread constructs AudioEncoder, just so long | 666 // Note: It doesn't matter which thread constructs AudioEncoder, just so long |
| 352 // as all calls to InsertAudio() are by the same thread. | 667 // as all calls to InsertAudio() are by the same thread. |
| 353 insert_thread_checker_.DetachFromThread(); | 668 insert_thread_checker_.DetachFromThread(); |
| 354 switch (codec) { | 669 switch (codec) { |
| 670 #if !defined(OS_IOS) | |
| 355 case CODEC_AUDIO_OPUS: | 671 case CODEC_AUDIO_OPUS: |
| 356 impl_ = new OpusImpl(cast_environment, | 672 impl_ = new OpusImpl(cast_environment, |
| 357 num_channels, | 673 num_channels, |
| 358 sampling_rate, | 674 sampling_rate, |
| 359 bitrate, | 675 bitrate, |
| 360 frame_encoded_callback); | 676 frame_encoded_callback); |
| 361 break; | 677 break; |
| 678 #endif | |
| 679 #if defined(OS_MACOSX) | |
| 680 case CODEC_AUDIO_AAC: | |
| 681 impl_ = new AacAudioConverterImpl(cast_environment, | |
| 682 num_channels, | |
| 683 sampling_rate, | |
| 684 bitrate, | |
| 685 frame_encoded_callback); | |
| 686 break; | |
| 687 #endif // defined(OS_MACOSX) | |
| 362 case CODEC_AUDIO_PCM16: | 688 case CODEC_AUDIO_PCM16: |
| 363 impl_ = new Pcm16Impl(cast_environment, | 689 impl_ = new Pcm16Impl(cast_environment, |
| 364 num_channels, | 690 num_channels, |
| 365 sampling_rate, | 691 sampling_rate, |
| 366 frame_encoded_callback); | 692 frame_encoded_callback); |
| 367 break; | 693 break; |
| 368 default: | 694 default: |
| 369 NOTREACHED() << "Unsupported or unspecified codec for audio encoder"; | 695 NOTREACHED() << "Unsupported or unspecified codec for audio encoder"; |
| 370 break; | 696 break; |
| 371 } | 697 } |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 401 cast_environment_->PostTask(CastEnvironment::AUDIO, | 727 cast_environment_->PostTask(CastEnvironment::AUDIO, |
| 402 FROM_HERE, | 728 FROM_HERE, |
| 403 base::Bind(&AudioEncoder::ImplBase::EncodeAudio, | 729 base::Bind(&AudioEncoder::ImplBase::EncodeAudio, |
| 404 impl_, | 730 impl_, |
| 405 base::Passed(&audio_bus), | 731 base::Passed(&audio_bus), |
| 406 recorded_time)); | 732 recorded_time)); |
| 407 } | 733 } |
| 408 | 734 |
| 409 } // namespace cast | 735 } // namespace cast |
| 410 } // namespace media | 736 } // namespace media |
| OLD | NEW |