1c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// found in the LICENSE file.
4c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
5c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/renderer/media/webrtc/video_destination_handler.h"
6c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
7c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include <string>
8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/base64.h"
10c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/logging.h"
11c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/rand_util.h"
12c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/strings/utf_string_conversions.h"
13c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/renderer/media/media_stream.h"
14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/renderer/media/media_stream_registry_interface.h"
15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/renderer/media/media_stream_video_track.h"
16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/renderer/pepper/ppb_image_data_impl.h"
17c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/renderer/render_thread_impl.h"
18c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "media/video/capture/video_capture_types.h"
19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "third_party/WebKit/public/platform/WebURL.h"
21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "third_party/libyuv/include/libyuv/convert.h"
23c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "url/gurl.h"
24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace content {
26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)class PpFrameWriter::FrameWriterDelegate
28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    : public base::RefCountedThreadSafe<FrameWriterDelegate> {
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) public:
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  FrameWriterDelegate(
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy,
32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      const VideoCaptureDeliverFrameCB& new_frame_callback);
33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void DeliverFrame(const scoped_refptr<media::VideoFrame>& frame,
35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                    const media::VideoCaptureFormat& format);
36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) private:
37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  friend class base::RefCountedThreadSafe<FrameWriterDelegate>;
38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  virtual ~FrameWriterDelegate();
39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void DeliverFrameOnIO(const scoped_refptr<media::VideoFrame>& frame,
41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                        const media::VideoCaptureFormat& format);
42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> io_message_loop_;
44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VideoCaptureDeliverFrameCB new_frame_callback_;
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)};
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)PpFrameWriter::FrameWriterDelegate::FrameWriterDelegate(
48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy,
49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const VideoCaptureDeliverFrameCB& new_frame_callback)
50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    : io_message_loop_(io_message_loop_proxy),
51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      new_frame_callback_(new_frame_callback) {
52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)PpFrameWriter::FrameWriterDelegate::~FrameWriterDelegate() {
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void PpFrameWriter::FrameWriterDelegate::DeliverFrame(
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const scoped_refptr<media::VideoFrame>& frame,
59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const media::VideoCaptureFormat& format) {
60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  io_message_loop_->PostTask(
61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      FROM_HERE,
62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&FrameWriterDelegate::DeliverFrameOnIO,
63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 this, frame, format));
64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void PpFrameWriter::FrameWriterDelegate::DeliverFrameOnIO(
67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)     const scoped_refptr<media::VideoFrame>& frame,
68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)     const media::VideoCaptureFormat& format) {
69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(io_message_loop_->BelongsToCurrentThread());
7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // The local time when this frame is generated is unknown so give a null
7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // value to |estimated_capture_time|.
7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  new_frame_callback_.Run(frame, format, base::TimeTicks());
73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)PpFrameWriter::PpFrameWriter() {
76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DVLOG(3) << "PpFrameWriter ctor";
77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochPpFrameWriter::~PpFrameWriter() {
80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DVLOG(3) << "PpFrameWriter dtor";
81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void PpFrameWriter::GetCurrentSupportedFormats(
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int max_requested_width,
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int max_requested_height,
86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const VideoCaptureDeviceFormatsCB& callback) {
87c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(CalledOnValidThread());
88c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DVLOG(3) << "PpFrameWriter::GetCurrentSupportedFormats()";
89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Since the input is free to change the resolution at any point in time
90010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // the supported formats are unknown.
91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  media::VideoCaptureFormats formats;
92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  callback.Run(formats);
93c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
94c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
95c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid PpFrameWriter::StartSourceImpl(
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const media::VideoCaptureParams& params,
97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const VideoCaptureDeliverFrameCB& frame_callback) {
98c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(CalledOnValidThread());
99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(!delegate_);
100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DVLOG(3) << "PpFrameWriter::StartSourceImpl()";
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  delegate_ = new FrameWriterDelegate(io_message_loop(), frame_callback);
102c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  OnStartDone(true);
103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
104c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
105c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid PpFrameWriter::StopSourceImpl() {
106c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(CalledOnValidThread());
107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
108c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
109c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid PpFrameWriter::PutFrame(PPB_ImageData_Impl* image_data,
110c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                             int64 time_stamp_ns) {
111c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(CalledOnValidThread());
112c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DVLOG(3) << "PpFrameWriter::PutFrame()";
113c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!image_data) {
115c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    LOG(ERROR) << "PpFrameWriter::PutFrame - Called with NULL image_data.";
116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
118c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ImageDataAutoMapper mapper(image_data);
119c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!mapper.is_valid()) {
120c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    LOG(ERROR) << "PpFrameWriter::PutFrame - "
121c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               << "The image could not be mapped and is unusable.";
122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
124c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const SkBitmap* bitmap = image_data->GetMappedBitmap();
125c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!bitmap) {
126c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    LOG(ERROR) << "PpFrameWriter::PutFrame - "
127c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               << "The image_data's mapped bitmap is NULL.";
128c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
129c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const gfx::Size frame_size(bitmap->width(), bitmap->height());
132c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
133c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (state() != MediaStreamVideoSource::STARTED)
134c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
135c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds(
1370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      time_stamp_ns / base::Time::kNanosecondsPerMicrosecond);
138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
139c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // TODO(perkj): It would be more efficient to use I420 here. Using YV12 will
140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // force a copy into a tightly packed I420 frame in
141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // WebRtcVideoCapturerAdapter before the frame is delivered to libJingle.
142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // crbug/359587.
143c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_refptr<media::VideoFrame> new_frame =
144c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      frame_pool_.CreateFrame(media::VideoFrame::YV12, frame_size,
145c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                              gfx::Rect(frame_size), frame_size, timestamp);
146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  media::VideoCaptureFormat format(
147010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      frame_size,
148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      MediaStreamVideoSource::kDefaultFrameRate,
149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      media::PIXEL_FORMAT_YV12);
150c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  libyuv::BGRAToI420(reinterpret_cast<uint8*>(bitmap->getPixels()),
152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     bitmap->rowBytes(),
153c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     new_frame->data(media::VideoFrame::kYPlane),
154c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     new_frame->stride(media::VideoFrame::kYPlane),
155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     new_frame->data(media::VideoFrame::kUPlane),
156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     new_frame->stride(media::VideoFrame::kUPlane),
157c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     new_frame->data(media::VideoFrame::kVPlane),
158c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     new_frame->stride(media::VideoFrame::kVPlane),
159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     frame_size.width(), frame_size.height());
160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
161010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  delegate_->DeliverFrame(new_frame, format);
162c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
163c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
164c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// PpFrameWriterProxy is a helper class to make sure the user won't use
165c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// PpFrameWriter after it is released (IOW its owner - WebMediaStreamSource -
166c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// is released).
167c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass PpFrameWriterProxy : public FrameWriterInterface {
168c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public:
169c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  explicit PpFrameWriterProxy(const base::WeakPtr<PpFrameWriter>& writer)
170c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      : writer_(writer) {
171c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    DCHECK(writer_ != NULL);
172c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
173c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
174c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual ~PpFrameWriterProxy() {}
175c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
176c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void PutFrame(PPB_ImageData_Impl* image_data,
177c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                        int64 time_stamp_ns) OVERRIDE {
178c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    writer_->PutFrame(image_data, time_stamp_ns);
179c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
180c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
181c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch private:
182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::WeakPtr<PpFrameWriter> writer_;
183c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
184c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DISALLOW_COPY_AND_ASSIGN(PpFrameWriterProxy);
185c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch};
186c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
187c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool VideoDestinationHandler::Open(
188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    MediaStreamRegistryInterface* registry,
189c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const std::string& url,
190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    FrameWriterInterface** frame_writer) {
191c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DVLOG(3) << "VideoDestinationHandler::Open";
192c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  blink::WebMediaStream stream;
193c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (registry) {
194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    stream = registry->GetMediaStream(url);
195c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  } else {
196c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    stream =
197c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url));
198c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
199c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (stream.isNull()) {
200c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    LOG(ERROR) << "VideoDestinationHandler::Open - invalid url: " << url;
201c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return false;
202c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
203c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
204c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Create a new native video track and add it to |stream|.
205c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::string track_id;
206c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // According to spec, a media stream source's id should be unique per
207c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // application. There's no easy way to strictly achieve that. The id
208c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // generated with this method should be unique for most of the cases but
209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // theoretically it's possible we can get an id that's duplicated with the
210c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // existing sources.
211c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::Base64Encode(base::RandBytesAsString(64), &track_id);
212010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  PpFrameWriter* writer = new PpFrameWriter();
214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
215c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Create a new webkit video track.
216c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  blink::WebMediaStreamSource webkit_source;
217c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  blink::WebMediaStreamSource::Type type =
218c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      blink::WebMediaStreamSource::TypeVideo;
219c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  blink::WebString webkit_track_id = base::UTF8ToUTF16(track_id);
220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  webkit_source.initialize(webkit_track_id, type, webkit_track_id);
221c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  webkit_source.setExtraData(writer);
222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
223c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  blink::WebMediaConstraints constraints;
224c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  constraints.initialize();
225c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool track_enabled = true;
226c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  stream.addTrack(MediaStreamVideoTrack::CreateVideoTrack(
228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      writer, constraints, MediaStreamVideoSource::ConstraintsCallback(),
2290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      track_enabled));
230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  *frame_writer = new PpFrameWriterProxy(writer->AsWeakPtr());
232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return true;
233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace content
236