blob: 089451e8b75cf8e7610de8516de5d2d3aee48fef [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/renderer/media/stream/media_stream_center.h"
#include <stddef.h>
#include <string>
#include <vector>
#include "base/command_line.h"
#include "base/logging.h"
#include "content/public/common/content_switches.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/media/stream/processed_local_audio_source.h"
#include "content/renderer/media/webrtc_local_audio_source_provider.h"
#include "media/base/sample_format.h"
#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_track.h"
#include "third_party/blink/public/platform/modules/mediastream/web_media_stream_audio_sink.h"
#include "third_party/blink/public/platform/modules/mediastream/web_platform_media_stream_source.h"
#include "third_party/blink/public/platform/modules/mediastream/webaudio_media_stream_source.h"
#include "third_party/blink/public/platform/web_media_constraints.h"
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/blink/public/platform/web_media_stream_source.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h"
#include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
#include "third_party/blink/public/web/web_frame.h"
using blink::WebFrame;
using blink::WebView;
namespace content {
namespace {
void CreateNativeAudioMediaStreamTrack(
const blink::WebMediaStreamTrack& track,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
blink::WebMediaStreamSource source = track.Source();
blink::MediaStreamAudioSource* media_stream_source =
blink::MediaStreamAudioSource::From(source);
// At this point, a MediaStreamAudioSource instance must exist. The one
// exception is when a WebAudio destination node is acting as a source of
// audio.
//
// TODO(miu): This needs to be moved to an appropriate location. A WebAudio
// source should have been created before this method was called so that this
// special case code isn't needed here.
if (!media_stream_source && source.RequiresAudioConsumer()) {
DVLOG(1) << "Creating WebAudio media stream source.";
media_stream_source =
new blink::WebAudioMediaStreamSource(&source, task_runner);
source.SetPlatformSource(
base::WrapUnique(media_stream_source)); // Takes ownership.
blink::WebMediaStreamSource::Capabilities capabilities;
capabilities.device_id = source.Id();
capabilities.echo_cancellation = std::vector<bool>({false});
capabilities.auto_gain_control = std::vector<bool>({false});
capabilities.noise_suppression = std::vector<bool>({false});
capabilities.sample_size = {
media::SampleFormatToBitsPerChannel(media::kSampleFormatS16), // min
media::SampleFormatToBitsPerChannel(media::kSampleFormatS16) // max
};
auto parameters = media_stream_source->GetAudioParameters();
if (parameters.IsValid()) {
capabilities.channel_count = {1, parameters.channels()};
capabilities.sample_rate = {parameters.sample_rate(),
parameters.sample_rate()};
capabilities.latency = {parameters.GetBufferDuration().InSecondsF(),
parameters.GetBufferDuration().InSecondsF()};
}
source.SetCapabilities(capabilities);
}
if (media_stream_source)
media_stream_source->ConnectToTrack(track);
else
LOG(DFATAL) << "WebMediaStreamSource missing its MediaStreamAudioSource.";
}
void CreateNativeVideoMediaStreamTrack(blink::WebMediaStreamTrack track) {
DCHECK(track.GetPlatformTrack() == nullptr);
blink::WebMediaStreamSource source = track.Source();
DCHECK_EQ(source.GetType(), blink::WebMediaStreamSource::kTypeVideo);
blink::MediaStreamVideoSource* native_source =
blink::MediaStreamVideoSource::GetVideoSource(source);
DCHECK(native_source);
track.SetPlatformTrack(std::make_unique<blink::MediaStreamVideoTrack>(
native_source, blink::MediaStreamVideoSource::ConstraintsCallback(),
track.IsEnabled()));
}
void CloneNativeVideoMediaStreamTrack(
const blink::WebMediaStreamTrack& original,
blink::WebMediaStreamTrack clone) {
DCHECK(!clone.GetPlatformTrack());
blink::WebMediaStreamSource source = clone.Source();
DCHECK_EQ(source.GetType(), blink::WebMediaStreamSource::kTypeVideo);
blink::MediaStreamVideoSource* native_source =
blink::MediaStreamVideoSource::GetVideoSource(source);
DCHECK(native_source);
blink::MediaStreamVideoTrack* original_track =
blink::MediaStreamVideoTrack::GetVideoTrack(original);
DCHECK(original_track);
clone.SetPlatformTrack(std::make_unique<blink::MediaStreamVideoTrack>(
native_source, original_track->adapter_settings(),
original_track->noise_reduction(), original_track->is_screencast(),
original_track->min_frame_rate(),
blink::MediaStreamVideoSource::ConstraintsCallback(), clone.IsEnabled()));
}
} // namespace
MediaStreamCenter::MediaStreamCenter(
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: task_runner_(task_runner) {}
MediaStreamCenter::~MediaStreamCenter() = default;
void MediaStreamCenter::DidCreateMediaStreamTrack(
const blink::WebMediaStreamTrack& track) {
DVLOG(1) << "MediaStreamCenter::didCreateMediaStreamTrack";
DCHECK(!track.IsNull() && !track.GetPlatformTrack());
DCHECK(!track.Source().IsNull());
switch (track.Source().GetType()) {
case blink::WebMediaStreamSource::kTypeAudio:
CreateNativeAudioMediaStreamTrack(track, task_runner_);
break;
case blink::WebMediaStreamSource::kTypeVideo:
CreateNativeVideoMediaStreamTrack(track);
break;
}
}
void MediaStreamCenter::DidCloneMediaStreamTrack(
const blink::WebMediaStreamTrack& original,
const blink::WebMediaStreamTrack& clone) {
DCHECK(!clone.IsNull());
DCHECK(!clone.GetPlatformTrack());
DCHECK(!clone.Source().IsNull());
switch (clone.Source().GetType()) {
case blink::WebMediaStreamSource::kTypeAudio:
CreateNativeAudioMediaStreamTrack(clone, task_runner_);
break;
case blink::WebMediaStreamSource::kTypeVideo:
CloneNativeVideoMediaStreamTrack(original, clone);
break;
}
}
void MediaStreamCenter::DidSetContentHint(
const blink::WebMediaStreamTrack& track) {
blink::WebPlatformMediaStreamTrack* native_track =
blink::WebPlatformMediaStreamTrack::GetTrack(track);
if (native_track)
native_track->SetContentHint(track.ContentHint());
}
void MediaStreamCenter::DidEnableMediaStreamTrack(
const blink::WebMediaStreamTrack& track) {
blink::WebPlatformMediaStreamTrack* native_track =
blink::WebPlatformMediaStreamTrack::GetTrack(track);
if (native_track)
native_track->SetEnabled(true);
}
void MediaStreamCenter::DidDisableMediaStreamTrack(
const blink::WebMediaStreamTrack& track) {
blink::WebPlatformMediaStreamTrack* native_track =
blink::WebPlatformMediaStreamTrack::GetTrack(track);
if (native_track)
native_track->SetEnabled(false);
}
blink::WebAudioSourceProvider*
MediaStreamCenter::CreateWebAudioSourceFromMediaStreamTrack(
const blink::WebMediaStreamTrack& track,
int context_sample_rate) {
DVLOG(1) << "MediaStreamCenter::createWebAudioSourceFromMediaStreamTrack";
blink::WebPlatformMediaStreamTrack* media_stream_track =
track.GetPlatformTrack();
if (!media_stream_track) {
DLOG(ERROR) << "Native track missing for webaudio source.";
return nullptr;
}
blink::WebMediaStreamSource source = track.Source();
DCHECK_EQ(source.GetType(), blink::WebMediaStreamSource::kTypeAudio);
// TODO(tommi): Rename WebRtcLocalAudioSourceProvider to
// WebAudioMediaStreamSink since it's not specific to any particular source.
// https://crbug.com/577874
return new WebRtcLocalAudioSourceProvider(track, context_sample_rate);
}
void MediaStreamCenter::DidStopMediaStreamSource(
const blink::WebMediaStreamSource& web_source) {
if (web_source.IsNull())
return;
blink::WebPlatformMediaStreamSource* const source =
web_source.GetPlatformSource();
DCHECK(source);
source->StopSource();
}
void MediaStreamCenter::GetSourceSettings(
const blink::WebMediaStreamSource& web_source,
blink::WebMediaStreamTrack::Settings& settings) {
blink::MediaStreamAudioSource* const source =
blink::MediaStreamAudioSource::From(web_source);
if (!source)
return;
media::AudioParameters audio_parameters = source->GetAudioParameters();
if (audio_parameters.IsValid()) {
settings.sample_rate = audio_parameters.sample_rate();
settings.channel_count = audio_parameters.channels();
settings.latency = audio_parameters.GetBufferDuration().InSecondsF();
}
// kSampleFormatS16 is the format used for all audio input streams.
settings.sample_size =
media::SampleFormatToBitsPerChannel(media::kSampleFormatS16);
}
} // namespace content