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