Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc

Issue 2133293003: [Chromecast] Make ALSA rendering delay either accurate or kNoTimestamp (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: Fix ALSA unit tests Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "chromecast/media/cma/backend/alsa/stream_mixer_alsa.h" 5 #include "chromecast/media/cma/backend/alsa/stream_mixer_alsa.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <limits>
9 #include <utility> 10 #include <utility>
10 11
11 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
12 #include "base/command_line.h" 13 #include "base/command_line.h"
13 #include "base/lazy_instance.h" 14 #include "base/lazy_instance.h"
14 #include "base/memory/weak_ptr.h" 15 #include "base/memory/weak_ptr.h"
15 #include "base/single_thread_task_runner.h" 16 #include "base/single_thread_task_runner.h"
16 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_number_conversions.h"
17 #include "base/threading/platform_thread.h" 18 #include "base/threading/platform_thread.h"
18 #include "base/threading/thread_task_runner_handle.h" 19 #include "base/threading/thread_task_runner_handle.h"
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 // direction they adjusted the requested parameter in, but since we read the 103 // direction they adjusted the requested parameter in, but since we read the
103 // output param and then log the information, this module doesn't need to get 104 // output param and then log the information, this module doesn't need to get
104 // the direction explicitly. 105 // the direction explicitly.
105 static int* kAlsaDirDontCare = nullptr; 106 static int* kAlsaDirDontCare = nullptr;
106 107
107 // These sample formats will be tried in order. 32 bit samples is ideal, but 108 // These sample formats will be tried in order. 32 bit samples is ideal, but
108 // some devices do not support 32 bit samples. 109 // some devices do not support 32 bit samples.
109 const snd_pcm_format_t kPreferredSampleFormats[] = {SND_PCM_FORMAT_S32, 110 const snd_pcm_format_t kPreferredSampleFormats[] = {SND_PCM_FORMAT_S32,
110 SND_PCM_FORMAT_S16}; 111 SND_PCM_FORMAT_S16};
111 112
113 const int64_t kNoTimestamp = std::numeric_limits<int64_t>::min();
114
112 int64_t TimespecToMicroseconds(struct timespec time) { 115 int64_t TimespecToMicroseconds(struct timespec time) {
113 return static_cast<int64_t>(time.tv_sec) * 116 return static_cast<int64_t>(time.tv_sec) *
114 base::Time::kMicrosecondsPerSecond + 117 base::Time::kMicrosecondsPerSecond +
115 time.tv_nsec / 1000; 118 time.tv_nsec / 1000;
116 } 119 }
117 120
118 bool GetSwitchValueAsInt(const std::string& switch_name, 121 bool GetSwitchValueAsInt(const std::string& switch_name,
119 int default_value, 122 int default_value,
120 int* value) { 123 int* value) {
121 DCHECK(value); 124 DCHECK(value);
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 } 530 }
528 531
529 if (post_loopback_filter_) { 532 if (post_loopback_filter_) {
530 post_loopback_filter_->SetSampleRateAndFormat( 533 post_loopback_filter_->SetSampleRateAndFormat(
531 output_samples_per_second_, ::media::SampleFormat::kSampleFormatS32); 534 output_samples_per_second_, ::media::SampleFormat::kSampleFormatS32);
532 } 535 }
533 536
534 RETURN_REPORT_ERROR(PcmPrepare, pcm_); 537 RETURN_REPORT_ERROR(PcmPrepare, pcm_);
535 RETURN_REPORT_ERROR(PcmStatusMalloc, &pcm_status_); 538 RETURN_REPORT_ERROR(PcmStatusMalloc, &pcm_status_);
536 539
537 struct timespec now = {0, 0}; 540 rendering_delay_.timestamp_microseconds = kNoTimestamp;
538 clock_gettime(CLOCK_MONOTONIC_RAW, &now);
539 rendering_delay_.timestamp_microseconds = TimespecToMicroseconds(now);
540 rendering_delay_.delay_microseconds = 0; 541 rendering_delay_.delay_microseconds = 0;
541 542
542 state_ = kStateNormalPlayback; 543 state_ = kStateNormalPlayback;
543 } 544 }
544 545
545 void StreamMixerAlsa::Stop() { 546 void StreamMixerAlsa::Stop() {
546 for (auto* observer : loopback_observers_) { 547 for (auto* observer : loopback_observers_) {
547 observer->OnLoopbackInterrupted(); 548 observer->OnLoopbackInterrupted();
548 } 549 }
549 550
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
822 int frames) { 823 int frames) {
823 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); 824 DCHECK(mixer_task_runner_->BelongsToCurrentThread());
824 CHECK_PCM_INITIALIZED(); 825 CHECK_PCM_INITIALIZED();
825 826
826 size_t interleaved_size = static_cast<size_t>(frames * kNumOutputChannels) * 827 size_t interleaved_size = static_cast<size_t>(frames * kNumOutputChannels) *
827 BytesPerOutputFormatSample(); 828 BytesPerOutputFormatSample();
828 if (interleaved_.size() < interleaved_size) { 829 if (interleaved_.size() < interleaved_size) {
829 interleaved_.resize(interleaved_size); 830 interleaved_.resize(interleaved_size);
830 } 831 }
831 832
832 int64_t expected_playback_time = rendering_delay_.timestamp_microseconds + 833 int64_t expected_playback_time;
833 rendering_delay_.delay_microseconds; 834 if (rendering_delay_.timestamp_microseconds == kNoTimestamp) {
835 expected_playback_time = kNoTimestamp;
836 } else {
837 expected_playback_time = rendering_delay_.timestamp_microseconds +
838 rendering_delay_.delay_microseconds;
839 }
840
834 mixed.ToInterleaved(frames, BytesPerOutputFormatSample(), 841 mixed.ToInterleaved(frames, BytesPerOutputFormatSample(),
835 interleaved_.data()); 842 interleaved_.data());
836 // Filter, send to observers, and post filter 843 // Filter, send to observers, and post filter
837 if (pre_loopback_filter_) { 844 if (pre_loopback_filter_) {
838 pre_loopback_filter_->ProcessInterleaved(interleaved_.data(), frames); 845 pre_loopback_filter_->ProcessInterleaved(interleaved_.data(), frames);
839 } 846 }
840 847
841 for (CastMediaShlib::LoopbackAudioObserver* observer : loopback_observers_) { 848 for (CastMediaShlib::LoopbackAudioObserver* observer : loopback_observers_) {
842 observer->OnLoopbackAudio(expected_playback_time, kSampleFormatS32, 849 observer->OnLoopbackAudio(expected_playback_time, kSampleFormatS32,
843 output_samples_per_second_, kNumOutputChannels, 850 output_samples_per_second_, kNumOutputChannels,
(...skipping 27 matching lines...) Expand all
871 } 878 }
872 UpdateRenderingDelay(frames); 879 UpdateRenderingDelay(frames);
873 for (auto&& input : inputs_) 880 for (auto&& input : inputs_)
874 input->AfterWriteFrames(rendering_delay_); 881 input->AfterWriteFrames(rendering_delay_);
875 } 882 }
876 883
877 void StreamMixerAlsa::UpdateRenderingDelay(int newly_pushed_frames) { 884 void StreamMixerAlsa::UpdateRenderingDelay(int newly_pushed_frames) {
878 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); 885 DCHECK(mixer_task_runner_->BelongsToCurrentThread());
879 CHECK_PCM_INITIALIZED(); 886 CHECK_PCM_INITIALIZED();
880 887
881 if (alsa_->PcmStatus(pcm_, pcm_status_) != 0) { 888 if (alsa_->PcmStatus(pcm_, pcm_status_) != 0 ||
882 // Estimate updated delay based on the number of frames we just pushed. 889 alsa_->PcmStatusGetState(pcm_status_) != SND_PCM_STATE_RUNNING) {
883 rendering_delay_.delay_microseconds += 890 rendering_delay_.timestamp_microseconds = kNoTimestamp;
884 static_cast<int64_t>(newly_pushed_frames) * 891 rendering_delay_.delay_microseconds = 0;
885 base::Time::kMicrosecondsPerSecond / output_samples_per_second_;
886 return; 892 return;
887 } 893 }
888 894
889 snd_htimestamp_t status_timestamp; 895 snd_htimestamp_t status_timestamp;
890 alsa_->PcmStatusGetHtstamp(pcm_status_, &status_timestamp); 896 alsa_->PcmStatusGetHtstamp(pcm_status_, &status_timestamp);
891 rendering_delay_.timestamp_microseconds = 897 rendering_delay_.timestamp_microseconds =
892 TimespecToMicroseconds(status_timestamp); 898 TimespecToMicroseconds(status_timestamp);
893 snd_pcm_sframes_t delay_frames = alsa_->PcmStatusGetDelay(pcm_status_); 899 snd_pcm_sframes_t delay_frames = alsa_->PcmStatusGetDelay(pcm_status_);
894 rendering_delay_.delay_microseconds = static_cast<int64_t>(delay_frames) * 900 rendering_delay_.delay_microseconds = static_cast<int64_t>(delay_frames) *
895 base::Time::kMicrosecondsPerSecond / 901 base::Time::kMicrosecondsPerSecond /
(...skipping 15 matching lines...) Expand all
911 DCHECK(std::find(loopback_observers_.begin(), loopback_observers_.end(), 917 DCHECK(std::find(loopback_observers_.begin(), loopback_observers_.end(),
912 observer) != loopback_observers_.end()); 918 observer) != loopback_observers_.end());
913 loopback_observers_.erase(std::remove(loopback_observers_.begin(), 919 loopback_observers_.erase(std::remove(loopback_observers_.begin(),
914 loopback_observers_.end(), observer), 920 loopback_observers_.end(), observer),
915 loopback_observers_.end()); 921 loopback_observers_.end());
916 observer->OnRemoved(); 922 observer->OnRemoved();
917 } 923 }
918 924
919 } // namespace media 925 } // namespace media
920 } // namespace chromecast 926 } // namespace chromecast
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698