legacy_encoded_audio_frame.cc (3481B)
1 /* 2 * Copyright (c) 2016 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 "modules/audio_coding/codecs/legacy_encoded_audio_frame.h" 12 13 #include <algorithm> 14 #include <cstddef> 15 #include <cstdint> 16 #include <memory> 17 #include <optional> 18 #include <utility> 19 #include <vector> 20 21 #include "api/array_view.h" 22 #include "api/audio_codecs/audio_decoder.h" 23 #include "rtc_base/buffer.h" 24 #include "rtc_base/checks.h" 25 26 namespace webrtc { 27 28 LegacyEncodedAudioFrame::LegacyEncodedAudioFrame(AudioDecoder* decoder, 29 Buffer&& payload) 30 : decoder_(decoder), payload_(std::move(payload)) {} 31 32 LegacyEncodedAudioFrame::~LegacyEncodedAudioFrame() = default; 33 34 size_t LegacyEncodedAudioFrame::Duration() const { 35 const int ret = decoder_->PacketDuration(payload_.data(), payload_.size()); 36 return (ret < 0) ? 0 : static_cast<size_t>(ret); 37 } 38 39 std::optional<AudioDecoder::EncodedAudioFrame::DecodeResult> 40 LegacyEncodedAudioFrame::Decode(ArrayView<int16_t> decoded) const { 41 AudioDecoder::SpeechType speech_type = AudioDecoder::kSpeech; 42 const int ret = decoder_->Decode( 43 payload_.data(), payload_.size(), decoder_->SampleRateHz(), 44 decoded.size() * sizeof(int16_t), decoded.data(), &speech_type); 45 46 if (ret < 0) 47 return std::nullopt; 48 49 return DecodeResult{.num_decoded_samples = static_cast<size_t>(ret), 50 .speech_type = speech_type}; 51 } 52 53 std::vector<AudioDecoder::ParseResult> LegacyEncodedAudioFrame::SplitBySamples( 54 AudioDecoder* decoder, 55 Buffer&& payload, 56 uint32_t timestamp, 57 size_t bytes_per_ms, 58 uint32_t timestamps_per_ms) { 59 RTC_DCHECK(payload.data()); 60 std::vector<AudioDecoder::ParseResult> results; 61 size_t split_size_bytes = payload.size(); 62 63 // Find a "chunk size" >= 20 ms and < 40 ms. 64 const size_t min_chunk_size = bytes_per_ms * 20; 65 if (min_chunk_size >= payload.size()) { 66 std::unique_ptr<LegacyEncodedAudioFrame> frame( 67 new LegacyEncodedAudioFrame(decoder, std::move(payload))); 68 results.emplace_back(timestamp, 0, std::move(frame)); 69 } else { 70 // Reduce the split size by half as long as `split_size_bytes` is at least 71 // twice the minimum chunk size (so that the resulting size is at least as 72 // large as the minimum chunk size). 73 while (split_size_bytes >= 2 * min_chunk_size) { 74 split_size_bytes /= 2; 75 } 76 77 const uint32_t timestamps_per_chunk = static_cast<uint32_t>( 78 split_size_bytes * timestamps_per_ms / bytes_per_ms); 79 size_t byte_offset; 80 uint32_t timestamp_offset; 81 for (byte_offset = 0, timestamp_offset = 0; byte_offset < payload.size(); 82 byte_offset += split_size_bytes, 83 timestamp_offset += timestamps_per_chunk) { 84 split_size_bytes = 85 std::min(split_size_bytes, payload.size() - byte_offset); 86 Buffer new_payload(payload.data() + byte_offset, split_size_bytes); 87 std::unique_ptr<LegacyEncodedAudioFrame> frame( 88 new LegacyEncodedAudioFrame(decoder, std::move(new_payload))); 89 results.emplace_back(timestamp + timestamp_offset, 0, std::move(frame)); 90 } 91 } 92 93 return results; 94 } 95 96 } // namespace webrtc