Skip to content

Commit

Permalink
MediaStreamDispatcher
Browse files Browse the repository at this point in the history
This is the second Chromium patch needed to support media streams 
http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#video-conferencing-and-peer-to-peer-communication. The first patch is here http://codereview.chromium.org/7192007/. 
The patch contain types needed in both the render and browser process and MediaStreamDispatcher that is used for sending request from the render process to the browser process for granting a webpage access to audio input and video capture devices.

BUG=none
TEST=none

Review URL: http://codereview.chromium.org/7184010

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@90752 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
perkj@google.com committed Jun 28, 2011
1 parent 4bdba60 commit 4712654
Show file tree
Hide file tree
Showing 10 changed files with 566 additions and 0 deletions.
1 change: 1 addition & 0 deletions chrome/chrome_tests.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -2012,6 +2012,7 @@
'../content/renderer/active_notification_tracker_unittest.cc',
'../content/renderer/media/audio_message_filter_unittest.cc',
'../content/renderer/media/audio_renderer_impl_unittest.cc',
'../content/renderer/media/media_stream_dispatcher_unittest.cc',
'../content/renderer/media/video_capture_impl_unittest.cc',
'../content/renderer/media/video_capture_message_filter_unittest.cc',
'../content/renderer/paint_aggregator_unittest.cc',
Expand Down
1 change: 1 addition & 0 deletions content/common/content_message_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "content/common/gpu/gpu_messages.h"
#include "content/common/indexed_db_messages.h"
#include "content/common/media/audio_messages.h"
#include "content/common/media/media_stream_messages.h"
#include "content/common/media/video_capture_messages.h"
#include "content/common/mime_registry_messages.h"
#include "content/common/p2p_messages.h"
Expand Down
66 changes: 66 additions & 0 deletions content/common/media/media_stream_messages.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) 2011 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.

// IPC messages for the media streaming.
// Multiply-included message file, hence no include guard.

#include <string>

#include "content/common/media/media_stream_options.h"
#include "ipc/ipc_message_macros.h"

#define IPC_MESSAGE_START MediaStreamMsgStart

IPC_ENUM_TRAITS(media_stream::MediaStreamType)
IPC_ENUM_TRAITS(media_stream::StreamOptions::VideoOption)

IPC_STRUCT_TRAITS_BEGIN(media_stream::StreamOptions)
IPC_STRUCT_TRAITS_MEMBER(audio)
IPC_STRUCT_TRAITS_MEMBER(video_option)
IPC_STRUCT_TRAITS_END()

IPC_STRUCT_TRAITS_BEGIN(media_stream::StreamDeviceInfo)
IPC_STRUCT_TRAITS_MEMBER(stream_type)
IPC_STRUCT_TRAITS_MEMBER(name)
IPC_STRUCT_TRAITS_MEMBER(device_id)
IPC_STRUCT_TRAITS_MEMBER(in_use)
IPC_STRUCT_TRAITS_MEMBER(session_id)
IPC_STRUCT_TRAITS_END()

// Message sent from the browser to the renderer

// The browser has generated a stream successfully.
IPC_MESSAGE_ROUTED4(MediaStreamMsg_StreamGenerated,
int /* request id */,
std::string /* label */,
media_stream::StreamDeviceInfoArray /* audio_device_list */,
media_stream::StreamDeviceInfoArray /* video_device_list */)

// The browser has failed to generate a stream.
IPC_MESSAGE_ROUTED1(MediaStreamMsg_StreamGenerationFailed,
int /* request id */)

// Report of a failure of a video device.
IPC_MESSAGE_ROUTED2(MediaStreamHostMsg_VideoDeviceFailed,
std::string /* label */,
int /* index */)

// Report of a failure of an audio device.
IPC_MESSAGE_ROUTED2(MediaStreamHostMsg_AudioDeviceFailed,
std::string /* label */,
int /* index */)

// Messages sent from the renderer to the browser.

// Request a new media stream.
IPC_MESSAGE_CONTROL4(MediaStreamHostMsg_GenerateStream,
int /* render view id */,
int /* request id */,
media_stream::StreamOptions /* options */,
std::string /* security origin */)

// Request to stop streaming from the media stream.
IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_StopGeneratedStream,
int /* render view id */,
std::string /* label */)
1 change: 1 addition & 0 deletions content/content_common.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
'common/main_function_params.h',
'common/media/audio_messages.h',
'common/media/audio_stream_state.h',
'common/media/media_stream_messages.h',
'common/media/media_stream_options.cc',
'common/media/media_stream_options.h',
'common/media/video_capture_messages.h',
Expand Down
3 changes: 3 additions & 0 deletions content/content_renderer.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@
'renderer/media/audio_message_filter.h',
'renderer/media/audio_renderer_impl.cc',
'renderer/media/audio_renderer_impl.h',
'renderer/media/media_stream_dispatcher.cc',
'renderer/media/media_stream_dispatcher.h',
'renderer/media/media_stream_dispatcher_eventhandler.h',
'renderer/media/video_capture_impl.cc',
'renderer/media/video_capture_impl.h',
'renderer/media/video_capture_impl_manager.cc',
Expand Down
157 changes: 157 additions & 0 deletions content/renderer/media/media_stream_dispatcher.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// Copyright (c) 2011 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/media_stream_dispatcher.h"

#include "base/logging.h"
#include "content/common/media/media_stream_messages.h"
#include "content/renderer/media/media_stream_dispatcher_eventhandler.h"

MediaStreamDispatcherEventHandler::~MediaStreamDispatcherEventHandler() {}

MediaStreamDispatcher::MediaStreamDispatcher(RenderView* render_view)
: RenderViewObserver(render_view),
next_ipc_id_(0) {
}

MediaStreamDispatcher::~MediaStreamDispatcher() {}

void MediaStreamDispatcher::GenerateStream(
int request_id,
MediaStreamDispatcherEventHandler* event_handler,
media_stream::StreamOptions components,
const std::string& security_origin) {
VLOG(1) << "MediaStreamDispatcher::GenerateStream(" << request_id << ")";

requests_.push_back(Request(event_handler, request_id, next_ipc_id_));
Send(new MediaStreamHostMsg_GenerateStream(routing_id(),
next_ipc_id_++,
components,
security_origin));
}

void MediaStreamDispatcher::StopStream(const std::string& label) {
VLOG(1) << "MediaStreamDispatcher::StopStream"
<< ", {label = " << label << "}";

LabelStreamMap::iterator it = label_stream_map_.find(label);
if (it == label_stream_map_.end())
return;

Send(new MediaStreamHostMsg_StopGeneratedStream(routing_id(), label));
label_stream_map_.erase(it);
}

bool MediaStreamDispatcher::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(MediaStreamDispatcher, message)
IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerated,
OnStreamGenerated)
IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed,
OnStreamGenerationFailed)
IPC_MESSAGE_HANDLER(MediaStreamHostMsg_VideoDeviceFailed,
OnVideoDeviceFailed)
IPC_MESSAGE_HANDLER(MediaStreamHostMsg_AudioDeviceFailed,
OnAudioDeviceFailed)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}

void MediaStreamDispatcher::OnStreamGenerated(
int request_id,
const std::string& label,
const media_stream::StreamDeviceInfoArray& audio_array,
const media_stream::StreamDeviceInfoArray& video_array) {

for (RequestList::iterator it = requests_.begin();
it != requests_.end(); ++it) {
Request& request = *it;
if (request.ipc_request == request_id) {
Stream new_stream;
new_stream.handler = request.handler;
new_stream.audio_array = audio_array;
new_stream.video_array = video_array;
label_stream_map_[label] = new_stream;
request.handler->OnStreamGenerated(request.request_id, label,
audio_array, video_array);
VLOG(1) << "MediaStreamDispatcher::OnStreamGenerated("
<< request.request_id << ", " << label << ")";
requests_.erase(it);
break;
}
}
}

void MediaStreamDispatcher::OnStreamGenerationFailed(int request_id) {
for (RequestList::iterator it = requests_.begin();
it != requests_.end(); ++it) {
Request& request = *it;
if (request.ipc_request == request_id) {
request.handler->OnStreamGenerationFailed(request.request_id);
VLOG(1) << "MediaStreamDispatcher::OnStreamGenerationFailed("
<< request.request_id << ")\n";
requests_.erase(it);
break;
}
}
}

void MediaStreamDispatcher::OnVideoDeviceFailed(const std::string& label,
int index) {
LabelStreamMap::iterator it = label_stream_map_.find(label);
if (it == label_stream_map_.end())
return;

// index is the index in the video_array that has failed.
DCHECK_GT(it->second.video_array.size(), static_cast<size_t>(index));
media_stream::StreamDeviceInfoArray::iterator device_it =
it->second.video_array.begin();
it->second.video_array.erase(device_it + index);
it->second.handler->OnVideoDeviceFailed(label, index);
}

void MediaStreamDispatcher::OnAudioDeviceFailed(const std::string& label,
int index) {
LabelStreamMap::iterator it = label_stream_map_.find(label);
if (it == label_stream_map_.end())
return;

// index is the index in the audio_array that has failed.
DCHECK_GT(it->second.audio_array.size(), static_cast<size_t>(index));
media_stream::StreamDeviceInfoArray::iterator device_it =
it->second.audio_array.begin();
it->second.audio_array.erase(device_it + index);
it->second.handler->OnAudioDeviceFailed(label, index);
}

int MediaStreamDispatcher::audio_session_id(const std::string& label,
int index) {
LabelStreamMap::iterator it = label_stream_map_.find(label);
if (it == label_stream_map_.end())
return media_stream::StreamDeviceInfo::kNoId;

DCHECK_GT(it->second.audio_array.size(), static_cast<size_t>(index));
return it->second.audio_array[index].session_id;
}

bool MediaStreamDispatcher::IsStream(const std::string& label) {
return label_stream_map_.find(label) != label_stream_map_.end();
}

int MediaStreamDispatcher::video_session_id(const std::string& label,
int index) {
LabelStreamMap::iterator it = label_stream_map_.find(label);
if (it == label_stream_map_.end())
return media_stream::StreamDeviceInfo::kNoId;

DCHECK_GT(it->second.video_array.size(), static_cast<size_t>(index));
return it->second.video_array[index].session_id;
}

MediaStreamDispatcher::Stream::Stream()
: handler(NULL) {}

MediaStreamDispatcher::Stream::~Stream() {}

96 changes: 96 additions & 0 deletions content/renderer/media/media_stream_dispatcher.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright (c) 2011 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.

#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_DISPATCHER_H_
#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_DISPATCHER_H_

#include <list>
#include <map>
#include <string>

#include "base/basictypes.h"
#include "base/message_loop.h"
#include "content/common/media/media_stream_options.h"
#include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
#include "content/renderer/render_view_observer.h"

// MediaStreamDispatcher is a delegate for the Media Stream API messages.
// MediaStreams are used by WebKit to open media devices such as Video Capture
// and Audio input devices.
// It's the complement of MediaStreamDispatcherHost (owned by
// BrowserRenderProcessHost).
class MediaStreamDispatcher : public RenderViewObserver {
public:
explicit MediaStreamDispatcher(RenderView* render_view);
virtual ~MediaStreamDispatcher();

// Request a new media stream to be created.
// This can be used either of WebKit or a plugin.
// Note: The event_handler must be valid for as long as the stream exists.
void GenerateStream(int request_id,
MediaStreamDispatcherEventHandler* event_handler,
media_stream::StreamOptions components,
const std::string& security_origin);

// Stop a started stream. Label is the label provided in OnStreamGenerated.
void StopStream(const std::string& label);

// Check if the label is a valid stream.
bool IsStream(const std::string& label);
// Get the video session_id given a label. The label identifies a stream.
// index is the index in the video_device_array of the stream.
int video_session_id(const std::string& label, int index);
// Returns an audio session_id given a label and an index.
int audio_session_id(const std::string& label, int index);

private:
FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, Basic);
FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, TestFailure);

struct Request {
Request(MediaStreamDispatcherEventHandler* handler,
int request_id,
int ipc_request)
: handler(handler),
request_id(request_id),
ipc_request(ipc_request) {
}
MediaStreamDispatcherEventHandler* handler;
int request_id;
int ipc_request;
};

// Private class for keeping track of opened devices and who have
// opened it.
struct Stream {
Stream();
~Stream();
MediaStreamDispatcherEventHandler* handler;
media_stream::StreamDeviceInfoArray audio_array;
media_stream::StreamDeviceInfoArray video_array;
};

// Messages from the browser.
virtual bool OnMessageReceived(const IPC::Message& message);
void OnStreamGenerated(
int request_id,
const std::string& label,
const media_stream::StreamDeviceInfoArray& audio_array,
const media_stream::StreamDeviceInfoArray& video_array);
void OnStreamGenerationFailed(int request_id);
void OnVideoDeviceFailed(const std::string& label, int index);
void OnAudioDeviceFailed(const std::string& label, int index);

int next_ipc_id_;
typedef std::map<std::string, Stream> LabelStreamMap;
LabelStreamMap label_stream_map_;

// List of calls made to GenerateStream that has not yet completed.
typedef std::list<Request> RequestList;
RequestList requests_;

DISALLOW_COPY_AND_ASSIGN(MediaStreamDispatcher);
};

#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_DISPATCHER_H_
39 changes: 39 additions & 0 deletions content/renderer/media/media_stream_dispatcher_eventhandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) 2011 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.

#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_DISPATCHER_EVENTHANDLER_H_
#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_DISPATCHER_EVENTHANDLER_H_

#include <string>

#include "content/common/media/media_stream_options.h"

class MediaStreamDispatcherEventHandler {
public:
// A new media stream have been created.
virtual void OnStreamGenerated(
int request_id,
const std::string& label,
const media_stream::StreamDeviceInfoArray& audio_device_array,
const media_stream::StreamDeviceInfoArray& video_device_array) = 0;

// Creation of a new media stream failed. The user might have denied access
// to the requested devices or no device is available.
virtual void OnStreamGenerationFailed(int request_id) = 0;

// An error have occurred on a video device. This is called if a runtime
// error occurs.
virtual void OnVideoDeviceFailed(const std::string& label,
int index) = 0;

// An error have occurred on an audio device. This is called if a runtime
// error occurs.
virtual void OnAudioDeviceFailed(const std::string& label,
int index) = 0;

protected:
virtual ~MediaStreamDispatcherEventHandler();
};

#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_DISPATCHER_EVENTHANDLER_H_
Loading

0 comments on commit 4712654

Please sign in to comment.