15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/renderer/pepper/pepper_media_stream_video_track_host.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/base64.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h"
9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/rand_util.h"
10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/strings/utf_string_conversions.h"
11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/renderer/media/media_stream_video_track.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "media/base/bind_to_current_loop.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "media/base/yuv_convert.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/c/pp_errors.h"
15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ppapi/c/ppb_media_stream_video_track.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/c/ppb_video_frame.h"
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ppapi/host/dispatch_host_message.h"
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ppapi/host/host_message_context.h"
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/shared_impl/media_stream_buffer.h"
21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// IS_ALIGNED is also defined in
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// third_party/webrtc/overrides/webrtc/base/basictypes.h
24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// TODO(ronghuawu): Avoid undef.
25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#undef IS_ALIGNED
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "third_party/libyuv/include/libyuv.h"
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using media::VideoFrame;
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using ppapi::host::HostMessageContext;
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using ppapi::MediaStreamVideoTrackShared;
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int32_t kDefaultNumberOfBuffers = 4;
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int32_t kMaxNumberOfBuffers = 8;
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Filter mode for scaling frames.
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const libyuv::FilterMode kFilterMode = libyuv::kFilterBox;
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kPepperVideoSourceName[] = "PepperVideoSourceName";
40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Default config for output mode.
42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const int kDefaultOutputFrameRate = 30;
43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)media::VideoPixelFormat ToPixelFormat(PP_VideoFrame_Format format) {
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  switch (format) {
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case PP_VIDEOFRAME_FORMAT_YV12:
47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return media::PIXEL_FORMAT_YV12;
48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case PP_VIDEOFRAME_FORMAT_I420:
49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return media::PIXEL_FORMAT_I420;
50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    default:
51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      DVLOG(1) << "Unsupported pixel format " << format;
52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return media::PIXEL_FORMAT_UNKNOWN;
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PP_VideoFrame_Format ToPpapiFormat(VideoFrame::Format format) {
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (format) {
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case VideoFrame::YV12:
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return PP_VIDEOFRAME_FORMAT_YV12;
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case VideoFrame::I420:
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return PP_VIDEOFRAME_FORMAT_I420;
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    default:
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DVLOG(1) << "Unsupported pixel format " << format;
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return PP_VIDEOFRAME_FORMAT_UNKNOWN;
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)VideoFrame::Format FromPpapiFormat(PP_VideoFrame_Format format) {
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  switch (format) {
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case PP_VIDEOFRAME_FORMAT_YV12:
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return VideoFrame::YV12;
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case PP_VIDEOFRAME_FORMAT_I420:
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return VideoFrame::I420;
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    default:
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DVLOG(1) << "Unsupported pixel format " << format;
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return VideoFrame::UNKNOWN;
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Compute size base on the size of frame received from MediaStreamVideoSink
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// and size specified by plugin.
82a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochgfx::Size GetTargetSize(const gfx::Size& source, const gfx::Size& plugin) {
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return gfx::Size(plugin.width() ? plugin.width() : source.width(),
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   plugin.height() ? plugin.height() : source.height());
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Compute format base on the format of frame received from MediaStreamVideoSink
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// and format specified by plugin.
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)PP_VideoFrame_Format GetTargetFormat(PP_VideoFrame_Format source,
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     PP_VideoFrame_Format plugin) {
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return plugin != PP_VIDEOFRAME_FORMAT_UNKNOWN ? plugin : source;
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ConvertFromMediaVideoFrame(const scoped_refptr<media::VideoFrame>& src,
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                PP_VideoFrame_Format dst_format,
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                const gfx::Size& dst_size,
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                uint8_t* dst) {
98a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  CHECK(src->format() == VideoFrame::YV12 || src->format() == VideoFrame::I420);
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (dst_format == PP_VIDEOFRAME_FORMAT_BGRA) {
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (src->coded_size() == dst_size) {
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      libyuv::I420ToARGB(src->data(VideoFrame::kYPlane),
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         src->stride(VideoFrame::kYPlane),
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         src->data(VideoFrame::kUPlane),
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         src->stride(VideoFrame::kUPlane),
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         src->data(VideoFrame::kVPlane),
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         src->stride(VideoFrame::kVPlane),
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         dst,
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         dst_size.width() * 4,
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         dst_size.width(),
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         dst_size.height());
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    } else {
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      media::ScaleYUVToRGB32(src->data(VideoFrame::kYPlane),
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             src->data(VideoFrame::kUPlane),
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             src->data(VideoFrame::kVPlane),
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             dst,
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             src->coded_size().width(),
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             src->coded_size().height(),
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             dst_size.width(),
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             dst_size.height(),
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             src->stride(VideoFrame::kYPlane),
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             src->stride(VideoFrame::kUPlane),
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             dst_size.width() * 4,
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             media::YV12,
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             media::ROTATE_0,
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             media::FILTER_BILINEAR);
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else if (dst_format == PP_VIDEOFRAME_FORMAT_YV12 ||
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             dst_format == PP_VIDEOFRAME_FORMAT_I420) {
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    static const size_t kPlanesOrder[][3] = {
130a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        {VideoFrame::kYPlane, VideoFrame::kVPlane,
131a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch         VideoFrame::kUPlane},  // YV12
132a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        {VideoFrame::kYPlane, VideoFrame::kUPlane,
133a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch         VideoFrame::kVPlane},  // I420
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    };
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const int plane_order = (dst_format == PP_VIDEOFRAME_FORMAT_YV12) ? 0 : 1;
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int dst_width = dst_size.width();
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int dst_height = dst_size.height();
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    libyuv::ScalePlane(src->data(kPlanesOrder[plane_order][0]),
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                       src->stride(kPlanesOrder[plane_order][0]),
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                       src->coded_size().width(),
141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                       src->coded_size().height(),
142a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       dst,
143a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       dst_width,
144a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       dst_width,
145a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       dst_height,
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                       kFilterMode);
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    dst += dst_width * dst_height;
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const int src_halfwidth = (src->coded_size().width() + 1) >> 1;
149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const int src_halfheight = (src->coded_size().height() + 1) >> 1;
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const int dst_halfwidth = (dst_width + 1) >> 1;
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const int dst_halfheight = (dst_height + 1) >> 1;
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    libyuv::ScalePlane(src->data(kPlanesOrder[plane_order][1]),
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                       src->stride(kPlanesOrder[plane_order][1]),
154a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       src_halfwidth,
155a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       src_halfheight,
156a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       dst,
157a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       dst_halfwidth,
158a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       dst_halfwidth,
159a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       dst_halfheight,
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                       kFilterMode);
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    dst += dst_halfwidth * dst_halfheight;
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    libyuv::ScalePlane(src->data(kPlanesOrder[plane_order][2]),
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                       src->stride(kPlanesOrder[plane_order][2]),
164a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       src_halfwidth,
165a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       src_halfheight,
166a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       dst,
167a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       dst_halfwidth,
168a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       dst_halfwidth,
169a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       dst_halfheight,
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                       kFilterMode);
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else {
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    NOTREACHED();
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace content {
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
180010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Internal class used for delivering video frames on the IO-thread to
181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// the MediaStreamVideoSource implementation.
182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)class PepperMediaStreamVideoTrackHost::FrameDeliverer
183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    : public base::RefCountedThreadSafe<FrameDeliverer> {
184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) public:
185010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  FrameDeliverer(
186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy,
187010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      const VideoCaptureDeliverFrameCB& new_frame_callback);
188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
189010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void DeliverVideoFrame(const scoped_refptr<media::VideoFrame>& frame,
190010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                         const media::VideoCaptureFormat& format);
191010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) private:
193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  friend class base::RefCountedThreadSafe<FrameDeliverer>;
194010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  virtual ~FrameDeliverer();
195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
196010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void DeliverFrameOnIO(const scoped_refptr<media::VideoFrame>& frame,
197010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                        const media::VideoCaptureFormat& format);
198010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
199010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> io_message_loop_;
200010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VideoCaptureDeliverFrameCB new_frame_callback_;
201010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
202010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FrameDeliverer);
203010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)};
204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
205010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)PepperMediaStreamVideoTrackHost::FrameDeliverer::FrameDeliverer(
206010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy,
207010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const VideoCaptureDeliverFrameCB& new_frame_callback)
208010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    : io_message_loop_(io_message_loop_proxy),
209010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      new_frame_callback_(new_frame_callback) {
210010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
211010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
212010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)PepperMediaStreamVideoTrackHost::FrameDeliverer::~FrameDeliverer() {
213010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
214010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
215010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void PepperMediaStreamVideoTrackHost::FrameDeliverer::DeliverVideoFrame(
216010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const scoped_refptr<media::VideoFrame>& frame,
217010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const media::VideoCaptureFormat& format) {
218010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  io_message_loop_->PostTask(
219010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      FROM_HERE,
220010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&FrameDeliverer::DeliverFrameOnIO,
221010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 this, frame, format));
222010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
223010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
224010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void PepperMediaStreamVideoTrackHost::FrameDeliverer::DeliverFrameOnIO(
225010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)     const scoped_refptr<media::VideoFrame>& frame,
226010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)     const media::VideoCaptureFormat& format) {
227010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(io_message_loop_->BelongsToCurrentThread());
22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // The time when this frame is generated is unknown so give a null value to
22946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // |estimated_capture_time|.
23046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  new_frame_callback_.Run(frame, format, base::TimeTicks());
231010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
232010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PepperMediaStreamVideoTrackHost::PepperMediaStreamVideoTrackHost(
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RendererPpapiHost* host,
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PP_Instance instance,
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PP_Resource resource,
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const blink::WebMediaStreamTrack& track)
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : PepperMediaStreamTrackHostBase(host, instance, resource),
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      track_(track),
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      connected_(false),
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      number_of_buffers_(kDefaultNumberOfBuffers),
242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      source_frame_format_(PP_VIDEOFRAME_FORMAT_UNKNOWN),
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      plugin_frame_format_(PP_VIDEOFRAME_FORMAT_UNKNOWN),
244010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      frame_data_size_(0),
245010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      type_(kRead),
246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      output_started_(false),
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      weak_factory_(this) {
248010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(!track_.isNull());
249010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
250010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
251010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)PepperMediaStreamVideoTrackHost::PepperMediaStreamVideoTrackHost(
252010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    RendererPpapiHost* host,
253010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    PP_Instance instance,
254010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    PP_Resource resource)
255010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    : PepperMediaStreamTrackHostBase(host, instance, resource),
256010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      connected_(false),
257010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      number_of_buffers_(kDefaultNumberOfBuffers),
258010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      source_frame_format_(PP_VIDEOFRAME_FORMAT_UNKNOWN),
259010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      plugin_frame_format_(PP_VIDEOFRAME_FORMAT_UNKNOWN),
260010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      frame_data_size_(0),
261010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      type_(kWrite),
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      output_started_(false),
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      weak_factory_(this) {
264010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  InitBlinkTrack();
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!track_.isNull());
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
268010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool PepperMediaStreamVideoTrackHost::IsMediaStreamVideoTrackHost() {
269010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return true;
270010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
271010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PepperMediaStreamVideoTrackHost::~PepperMediaStreamVideoTrackHost() {
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  OnClose();
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void PepperMediaStreamVideoTrackHost::InitBuffers() {
277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Size size = GetTargetSize(source_frame_size_, plugin_frame_size_);
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(!size.IsEmpty());
279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  PP_VideoFrame_Format format =
281a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      GetTargetFormat(source_frame_format_, plugin_frame_format_);
282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_NE(format, PP_VIDEOFRAME_FORMAT_UNKNOWN);
283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (format == PP_VIDEOFRAME_FORMAT_BGRA) {
285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    frame_data_size_ = size.width() * size.height() * 4;
286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else {
287a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    frame_data_size_ =
288a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        VideoFrame::AllocationSize(FromPpapiFormat(format), size);
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_GT(frame_data_size_, 0U);
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int32_t buffer_size =
293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      sizeof(ppapi::MediaStreamBuffer::Video) + frame_data_size_;
294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool result = PepperMediaStreamTrackHostBase::InitBuffers(number_of_buffers_,
295010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                            buffer_size,
296010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                            type_);
297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CHECK(result);
298010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
299010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (type_ == kWrite) {
300010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    for (int32_t i = 0; i < buffer_manager()->number_of_buffers(); ++i) {
301010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ppapi::MediaStreamBuffer::Video* buffer =
302010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          &(buffer_manager()->GetBufferPointer(i)->video);
303010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      buffer->header.size = buffer_manager()->buffer_size();
304010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      buffer->header.type = ppapi::MediaStreamBuffer::TYPE_VIDEO;
305010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      buffer->format = format;
306010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      buffer->size.width = size.width();
307010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      buffer->size.height = size.height();
308010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      buffer->data_size = frame_data_size_;
309010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
310010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
311010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Make all the frames avaiable to the plugin.
312010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    std::vector<int32_t> indices = buffer_manager()->DequeueBuffers();
313010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SendEnqueueBuffersMessageToPlugin(indices);
314010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PepperMediaStreamVideoTrackHost::OnClose() {
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (connected_) {
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MediaStreamVideoSink::RemoveFromVideoTrack(this, track_);
320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    weak_factory_.InvalidateWeakPtrs();
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    connected_ = false;
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
325010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)int32_t PepperMediaStreamVideoTrackHost::OnHostMsgEnqueueBuffer(
326010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ppapi::host::HostMessageContext* context, int32_t index) {
327010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (type_ == kRead) {
328010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return PepperMediaStreamTrackHostBase::OnHostMsgEnqueueBuffer(context,
329010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                                  index);
330010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else {
331010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return SendFrameToTrack(index);
332010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
333010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
334010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
335010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)int32_t PepperMediaStreamVideoTrackHost::SendFrameToTrack(int32_t index) {
336010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_EQ(type_, kWrite);
337010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
338010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (output_started_) {
339010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Sends the frame to blink video track.
340010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ppapi::MediaStreamBuffer::Video* pp_frame =
341010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        &(buffer_manager()->GetBufferPointer(index)->video);
342010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
343010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int32 y_stride = plugin_frame_size_.width();
344010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int32 uv_stride = (plugin_frame_size_.width() + 1) / 2;
345010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    uint8* y_data = static_cast<uint8*>(pp_frame->data);
346010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Default to I420
347010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    uint8* u_data = y_data + plugin_frame_size_.GetArea();
348010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    uint8* v_data = y_data + (plugin_frame_size_.GetArea() * 5 / 4);
349010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (plugin_frame_format_ == PP_VIDEOFRAME_FORMAT_YV12) {
350010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // Swap u and v for YV12.
351010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      uint8* tmp = u_data;
352010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      u_data = v_data;
353010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      v_data = tmp;
354010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
355010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
356010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int64 ts_ms = static_cast<int64>(pp_frame->timestamp *
357010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                     base::Time::kMillisecondsPerSecond);
358010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_refptr<VideoFrame> frame = media::VideoFrame::WrapExternalYuvData(
359010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        FromPpapiFormat(plugin_frame_format_),
360010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        plugin_frame_size_,
361010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        gfx::Rect(plugin_frame_size_),
362010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        plugin_frame_size_,
363010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        y_stride,
364010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        uv_stride,
365010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        uv_stride,
366010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        y_data,
367010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        u_data,
368010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        v_data,
369010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        base::TimeDelta::FromMilliseconds(ts_ms),
370010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        base::Closure());
371010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
372010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    frame_deliverer_->DeliverVideoFrame(
373010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        frame,
374010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        media::VideoCaptureFormat(plugin_frame_size_,
375010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                  kDefaultOutputFrameRate,
376010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                  ToPixelFormat(plugin_frame_format_)));
377010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
378010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
379010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Makes the frame available again for plugin.
380010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  SendEnqueueBufferMessageToPlugin(index);
381010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return PP_OK;
382010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
383010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PepperMediaStreamVideoTrackHost::OnVideoFrame(
385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const scoped_refptr<VideoFrame>& frame,
38646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const media::VideoCaptureFormat& format,
38746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const base::TimeTicks& estimated_capture_time) {
3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(frame.get());
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(penghuang): Check |frame->end_of_stream()| and close the track.
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_VideoFrame_Format ppformat = ToPpapiFormat(frame->format());
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ppformat == PP_VIDEOFRAME_FORMAT_UNKNOWN)
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (source_frame_size_.IsEmpty()) {
395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    source_frame_size_ = frame->coded_size();
396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    source_frame_format_ = ppformat;
397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    InitBuffers();
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int32_t index = buffer_manager()->DequeueBuffer();
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Drop frames if the underlying buffer is full.
402a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (index < 0) {
403a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DVLOG(1) << "A frame is dropped.";
4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
406a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
407a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CHECK_EQ(ppformat, source_frame_format_) << "Frame format is changed.";
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
409a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Size size = GetTargetSize(source_frame_size_, plugin_frame_size_);
410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ppformat =
411a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      GetTargetFormat(source_frame_format_, plugin_frame_format_);
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ppapi::MediaStreamBuffer::Video* buffer =
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      &(buffer_manager()->GetBufferPointer(index)->video);
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  buffer->header.size = buffer_manager()->buffer_size();
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  buffer->header.type = ppapi::MediaStreamBuffer::TYPE_VIDEO;
416c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  buffer->timestamp = frame->timestamp().InSecondsF();
417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  buffer->format = ppformat;
418a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  buffer->size.width = size.width();
419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  buffer->size.height = size.height();
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  buffer->data_size = frame_data_size_;
421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ConvertFromMediaVideoFrame(frame, ppformat, size, buffer->data);
422010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SendEnqueueBufferMessageToPlugin(index);
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
426010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void PepperMediaStreamVideoTrackHost::GetCurrentSupportedFormats(
427010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int max_requested_width, int max_requested_height,
4285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    double max_requested_frame_rate,
429010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const VideoCaptureDeviceFormatsCB& callback) {
430010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (type_ != kWrite) {
431010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    DVLOG(1) << "GetCurrentSupportedFormats is only supported in output mode.";
432010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    callback.Run(media::VideoCaptureFormats());
433010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
434010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
435010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
436010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  media::VideoCaptureFormats formats;
437010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  formats.push_back(
438010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      media::VideoCaptureFormat(plugin_frame_size_,
439010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                kDefaultOutputFrameRate,
440010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                ToPixelFormat(plugin_frame_format_)));
441010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  callback.Run(formats);
442010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
443010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
444010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void PepperMediaStreamVideoTrackHost::StartSourceImpl(
4451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const media::VideoCaptureFormat& format,
446010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const VideoCaptureDeliverFrameCB& frame_callback) {
447010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  output_started_ = true;
448010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  frame_deliverer_ = new FrameDeliverer(io_message_loop(), frame_callback);
449010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
450010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
451010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void PepperMediaStreamVideoTrackHost::StopSourceImpl() {
452010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  output_started_ = false;
453010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  frame_deliverer_ = NULL;
454010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
455010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PepperMediaStreamVideoTrackHost::DidConnectPendingHostToResource() {
4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!connected_) {
458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MediaStreamVideoSink::AddToVideoTrack(
459cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        this,
460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        media::BindToCurrentLoop(
461cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            base::Bind(
462cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                &PepperMediaStreamVideoTrackHost::OnVideoFrame,
463cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                weak_factory_.GetWeakPtr())),
464cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        track_);
4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    connected_ = true;
4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
469a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int32_t PepperMediaStreamVideoTrackHost::OnResourceMessageReceived(
470a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const IPC::Message& msg,
471a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    HostMessageContext* context) {
472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PPAPI_BEGIN_MESSAGE_MAP(PepperMediaStreamVideoTrackHost, msg)
473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(
474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        PpapiHostMsg_MediaStreamVideoTrack_Configure, OnHostMsgConfigure)
475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PPAPI_END_MESSAGE_MAP()
476a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return PepperMediaStreamTrackHostBase::OnResourceMessageReceived(msg,
477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                                   context);
478a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
479a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
480a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int32_t PepperMediaStreamVideoTrackHost::OnHostMsgConfigure(
481a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    HostMessageContext* context,
482a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const MediaStreamVideoTrackShared::Attributes& attributes) {
483a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CHECK(MediaStreamVideoTrackShared::VerifyAttributes(attributes));
484a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool changed = false;
486a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Size new_size(attributes.width, attributes.height);
487a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (GetTargetSize(source_frame_size_, plugin_frame_size_) !=
488a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      GetTargetSize(source_frame_size_, new_size)) {
489a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    changed = true;
490a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
491a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  plugin_frame_size_ = new_size;
492a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
493a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  int32_t buffers = attributes.buffers
494a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                        ? std::min(kMaxNumberOfBuffers, attributes.buffers)
495a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                        : kDefaultNumberOfBuffers;
496a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (buffers != number_of_buffers_)
497a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    changed = true;
498a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  number_of_buffers_ = buffers;
499a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
500a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (GetTargetFormat(source_frame_format_, plugin_frame_format_) !=
501a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      GetTargetFormat(source_frame_format_, attributes.format)) {
502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    changed = true;
503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  plugin_frame_format_ = attributes.format;
505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
506a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // If the first frame has been received, we will re-initialize buffers with
507a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // new settings. Otherwise, we will initialize buffer when we receive
508a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // the first frame, because plugin can only provide part of attributes
509a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // which are not enough to initialize buffers.
510010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (changed && (type_ == kWrite || !source_frame_size_.IsEmpty()))
511a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    InitBuffers();
512a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
513010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // TODO(ronghuawu): Ask the owner of DOMMediaStreamTrackToResource why
514010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // source id instead of track id is used there.
515010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const std::string id = track_.source().id().utf8();
516010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  context->reply_msg = PpapiPluginMsg_MediaStreamVideoTrack_ConfigureReply(id);
517a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return PP_OK;
518a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
519a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
520010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void PepperMediaStreamVideoTrackHost::InitBlinkTrack() {
521010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string source_id;
522010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::Base64Encode(base::RandBytesAsString(64), &source_id);
523010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  blink::WebMediaStreamSource webkit_source;
524010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  webkit_source.initialize(base::UTF8ToUTF16(source_id),
525010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                           blink::WebMediaStreamSource::TypeVideo,
526010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                           base::UTF8ToUTF16(kPepperVideoSourceName));
527010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  webkit_source.setExtraData(this);
528010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
529010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const bool enabled = true;
530010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  blink::WebMediaConstraints constraints;
531010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  constraints.initialize();
532010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  track_ = MediaStreamVideoTrack::CreateVideoTrack(
533010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       this, constraints,
534010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       base::Bind(
535010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           &PepperMediaStreamVideoTrackHost::OnTrackStarted,
536010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           base::Unretained(this)),
537010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       enabled);
538010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
539010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
540010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void PepperMediaStreamVideoTrackHost::OnTrackStarted(
5416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    MediaStreamSource* source,
5426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    MediaStreamRequestResult result,
5436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const blink::WebString& result_name) {
5446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DVLOG(3) << "OnTrackStarted result: " << result;
545010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
546010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace content
548