Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / renderer / media / webrtc / video_destination_handler.cc
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/renderer/media/webrtc/video_destination_handler.h"
6
7 #include <string>
8
9 #include "base/base64.h"
10 #include "base/debug/trace_event.h"
11 #include "base/logging.h"
12 #include "base/rand_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "content/renderer/media/media_stream.h"
15 #include "content/renderer/media/media_stream_registry_interface.h"
16 #include "content/renderer/media/media_stream_video_track.h"
17 #include "content/renderer/pepper/ppb_image_data_impl.h"
18 #include "content/renderer/render_thread_impl.h"
19 #include "media/video/capture/video_capture_types.h"
20 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
21 #include "third_party/WebKit/public/platform/WebURL.h"
22 #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
23 #include "third_party/libyuv/include/libyuv/convert.h"
24 #include "url/gurl.h"
25
26 namespace content {
27
28 class PpFrameWriter::FrameWriterDelegate
29     : public base::RefCountedThreadSafe<FrameWriterDelegate> {
30  public:
31   FrameWriterDelegate(
32       const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy,
33       const VideoCaptureDeliverFrameCB& new_frame_callback);
34
35   void DeliverFrame(const scoped_refptr<media::VideoFrame>& frame,
36                     const media::VideoCaptureFormat& format);
37  private:
38   friend class base::RefCountedThreadSafe<FrameWriterDelegate>;
39   virtual ~FrameWriterDelegate();
40
41   void DeliverFrameOnIO(const scoped_refptr<media::VideoFrame>& frame,
42                         const media::VideoCaptureFormat& format);
43
44   scoped_refptr<base::MessageLoopProxy> io_message_loop_;
45   VideoCaptureDeliverFrameCB new_frame_callback_;
46 };
47
48 PpFrameWriter::FrameWriterDelegate::FrameWriterDelegate(
49     const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy,
50     const VideoCaptureDeliverFrameCB& new_frame_callback)
51     : io_message_loop_(io_message_loop_proxy),
52       new_frame_callback_(new_frame_callback) {
53 }
54
55 PpFrameWriter::FrameWriterDelegate::~FrameWriterDelegate() {
56 }
57
58 void PpFrameWriter::FrameWriterDelegate::DeliverFrame(
59     const scoped_refptr<media::VideoFrame>& frame,
60     const media::VideoCaptureFormat& format) {
61   io_message_loop_->PostTask(
62       FROM_HERE,
63       base::Bind(&FrameWriterDelegate::DeliverFrameOnIO,
64                  this, frame, format));
65 }
66
67 void PpFrameWriter::FrameWriterDelegate::DeliverFrameOnIO(
68      const scoped_refptr<media::VideoFrame>& frame,
69      const media::VideoCaptureFormat& format) {
70   DCHECK(io_message_loop_->BelongsToCurrentThread());
71   // The local time when this frame is generated is unknown so give a null
72   // value to |estimated_capture_time|.
73   new_frame_callback_.Run(frame, format, base::TimeTicks());
74 }
75
76 PpFrameWriter::PpFrameWriter() {
77   DVLOG(3) << "PpFrameWriter ctor";
78 }
79
80 PpFrameWriter::~PpFrameWriter() {
81   DVLOG(3) << "PpFrameWriter dtor";
82 }
83
84 void PpFrameWriter::GetCurrentSupportedFormats(
85     int max_requested_width,
86     int max_requested_height,
87     double max_requested_frame_rate,
88     const VideoCaptureDeviceFormatsCB& callback) {
89   DCHECK(CalledOnValidThread());
90   DVLOG(3) << "PpFrameWriter::GetCurrentSupportedFormats()";
91   // Since the input is free to change the resolution at any point in time
92   // the supported formats are unknown.
93   media::VideoCaptureFormats formats;
94   callback.Run(formats);
95 }
96
97 void PpFrameWriter::StartSourceImpl(
98     const media::VideoCaptureFormat& format,
99     const VideoCaptureDeliverFrameCB& frame_callback) {
100   DCHECK(CalledOnValidThread());
101   DCHECK(!delegate_.get());
102   DVLOG(3) << "PpFrameWriter::StartSourceImpl()";
103   delegate_ = new FrameWriterDelegate(io_message_loop(), frame_callback);
104   OnStartDone(MEDIA_DEVICE_OK);
105 }
106
107 void PpFrameWriter::StopSourceImpl() {
108   DCHECK(CalledOnValidThread());
109 }
110
111 // Note: PutFrame must copy or process image_data directly in this function,
112 // because it may be overwritten as soon as we return from this function.
113 void PpFrameWriter::PutFrame(PPB_ImageData_Impl* image_data,
114                              int64 time_stamp_ns) {
115   DCHECK(CalledOnValidThread());
116   TRACE_EVENT0("video", "PpFrameWriter::PutFrame");
117   DVLOG(3) << "PpFrameWriter::PutFrame()";
118
119   if (!image_data) {
120     LOG(ERROR) << "PpFrameWriter::PutFrame - Called with NULL image_data.";
121     return;
122   }
123   ImageDataAutoMapper mapper(image_data);
124   if (!mapper.is_valid()) {
125     LOG(ERROR) << "PpFrameWriter::PutFrame - "
126                << "The image could not be mapped and is unusable.";
127     return;
128   }
129   const SkBitmap* bitmap = image_data->GetMappedBitmap();
130   if (!bitmap) {
131     LOG(ERROR) << "PpFrameWriter::PutFrame - "
132                << "The image_data's mapped bitmap is NULL.";
133     return;
134   }
135
136   const uint8* src_data = static_cast<uint8*>(bitmap->getPixels());
137   const int src_stride = static_cast<int>(bitmap->rowBytes());
138   const int width = bitmap->width();
139   const int height = bitmap->height();
140
141   // We only support PP_IMAGEDATAFORMAT_BGRA_PREMUL at the moment.
142   DCHECK(image_data->format() == PP_IMAGEDATAFORMAT_BGRA_PREMUL);
143
144   const gfx::Size frame_size(width, height);
145
146   if (state() != MediaStreamVideoSource::STARTED)
147     return;
148
149   const base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds(
150       time_stamp_ns / base::Time::kNanosecondsPerMicrosecond);
151
152   scoped_refptr<media::VideoFrame> new_frame =
153       frame_pool_.CreateFrame(media::VideoFrame::YV12, frame_size,
154                               gfx::Rect(frame_size), frame_size, timestamp);
155   media::VideoCaptureFormat format(
156       frame_size,
157       MediaStreamVideoSource::kUnknownFrameRate,
158       media::PIXEL_FORMAT_YV12);
159
160   libyuv::ARGBToI420(src_data,
161                      src_stride,
162                      new_frame->data(media::VideoFrame::kYPlane),
163                      new_frame->stride(media::VideoFrame::kYPlane),
164                      new_frame->data(media::VideoFrame::kUPlane),
165                      new_frame->stride(media::VideoFrame::kUPlane),
166                      new_frame->data(media::VideoFrame::kVPlane),
167                      new_frame->stride(media::VideoFrame::kVPlane),
168                      width,
169                      height);
170
171   delegate_->DeliverFrame(new_frame, format);
172 }
173
174 // PpFrameWriterProxy is a helper class to make sure the user won't use
175 // PpFrameWriter after it is released (IOW its owner - WebMediaStreamSource -
176 // is released).
177 class PpFrameWriterProxy : public FrameWriterInterface {
178  public:
179   explicit PpFrameWriterProxy(const base::WeakPtr<PpFrameWriter>& writer)
180       : writer_(writer) {
181     DCHECK(writer_ != NULL);
182   }
183
184   virtual ~PpFrameWriterProxy() {}
185
186   virtual void PutFrame(PPB_ImageData_Impl* image_data,
187                         int64 time_stamp_ns) override {
188     writer_->PutFrame(image_data, time_stamp_ns);
189   }
190
191  private:
192   base::WeakPtr<PpFrameWriter> writer_;
193
194   DISALLOW_COPY_AND_ASSIGN(PpFrameWriterProxy);
195 };
196
197 bool VideoDestinationHandler::Open(
198     MediaStreamRegistryInterface* registry,
199     const std::string& url,
200     FrameWriterInterface** frame_writer) {
201   DVLOG(3) << "VideoDestinationHandler::Open";
202   blink::WebMediaStream stream;
203   if (registry) {
204     stream = registry->GetMediaStream(url);
205   } else {
206     stream =
207         blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url));
208   }
209   if (stream.isNull()) {
210     LOG(ERROR) << "VideoDestinationHandler::Open - invalid url: " << url;
211     return false;
212   }
213
214   // Create a new native video track and add it to |stream|.
215   std::string track_id;
216   // According to spec, a media stream source's id should be unique per
217   // application. There's no easy way to strictly achieve that. The id
218   // generated with this method should be unique for most of the cases but
219   // theoretically it's possible we can get an id that's duplicated with the
220   // existing sources.
221   base::Base64Encode(base::RandBytesAsString(64), &track_id);
222
223   PpFrameWriter* writer = new PpFrameWriter();
224
225   // Create a new webkit video track.
226   blink::WebMediaStreamSource webkit_source;
227   blink::WebMediaStreamSource::Type type =
228       blink::WebMediaStreamSource::TypeVideo;
229   blink::WebString webkit_track_id = base::UTF8ToUTF16(track_id);
230   webkit_source.initialize(webkit_track_id, type, webkit_track_id);
231   webkit_source.setExtraData(writer);
232
233   blink::WebMediaConstraints constraints;
234   constraints.initialize();
235   bool track_enabled = true;
236
237   stream.addTrack(MediaStreamVideoTrack::CreateVideoTrack(
238       writer, constraints, MediaStreamVideoSource::ConstraintsCallback(),
239       track_enabled));
240
241   *frame_writer = new PpFrameWriterProxy(writer->AsWeakPtr());
242   return true;
243 }
244
245 }  // namespace content