Chromium Code Reviews| Index: content/renderer/pepper/pepper_media_stream_video_track_host.cc |
| diff --git a/content/renderer/pepper/pepper_media_stream_video_track_host.cc b/content/renderer/pepper/pepper_media_stream_video_track_host.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..8e33439d1d6b36f28c1c8d6c2fb37ec18c34796e |
| --- /dev/null |
| +++ b/content/renderer/pepper/pepper_media_stream_video_track_host.cc |
| @@ -0,0 +1,122 @@ |
| +// Copyright (c) 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/renderer/pepper/pepper_media_stream_video_track_host.h" |
| + |
| +#include "ppapi/c/pp_errors.h" |
| +#include "ppapi/c/ppb_video_frame.h" |
| +#include "ppapi/shared_impl/media_stream_frame.h" |
| + |
| +using media::VideoFrame; |
| + |
| +namespace { |
| + |
| +// TODO(penghuang): make it configurable. |
| +const int32_t kNumberOfFrames = 4; |
| + |
| +PP_VideoFrame_Format ToPpapiFormat(VideoFrame::Format format) { |
| + switch (format) { |
| + case VideoFrame::YV12: |
| + return PP_VIDEOFRAME_FORMAT_YV12; |
| + case VideoFrame::YV16: |
| + return PP_VIDEOFRAME_FORMAT_YV16; |
| + case VideoFrame::I420: |
| + return PP_VIDEOFRAME_FORMAT_I420; |
| + case VideoFrame::YV12A: |
| + return PP_VIDEOFRAME_FORMAT_YV12A; |
| + case VideoFrame::YV12J: |
| + return PP_VIDEOFRAME_FORMAT_YV12J; |
| + default: |
| + DVLOG(1) << "Unsupported pixel format " << format; |
| + return PP_VIDEOFRAME_FORMAT_UNKNOWN; |
| + } |
| +} |
| + |
| +} // namespace |
| + |
| +namespace content { |
| + |
| +PepperMediaStreamVideoTrackHost::PepperMediaStreamVideoTrackHost( |
| + RendererPpapiHost* host, |
| + PP_Instance instance, |
| + PP_Resource resource, |
| + const blink::WebMediaStreamTrack& track) |
| + : PepperMediaStreamTrackHostBase(host, instance, resource), |
| + track_(track), |
| + connected_(false), |
| + frame_format_(VideoFrame::UNKNOWN), |
| + frame_data_size_(0) { |
| + DCHECK(!track_.isNull()); |
| +} |
| + |
| +PepperMediaStreamVideoTrackHost::~PepperMediaStreamVideoTrackHost() { |
| + OnClose(); |
| +} |
| + |
| +void PepperMediaStreamVideoTrackHost::OnClose() { |
| + if (connected_) { |
| + MediaStreamVideoSink::RemoveFromVideoTrack(this, track_); |
| + connected_ = false; |
| + } |
| +} |
| + |
| +void PepperMediaStreamVideoTrackHost::OnVideoFrame( |
| + const scoped_refptr<VideoFrame>& frame) { |
| + DCHECK(frame); |
| + PP_VideoFrame_Format ppformat = ToPpapiFormat(frame->format()); |
| + if (ppformat == PP_VIDEOFRAME_FORMAT_UNKNOWN) |
| + return; |
| + |
| + if (frame_size_ != frame->coded_size() || frame_format_ != frame->format()) { |
| + frame_size_ = frame->coded_size(); |
| + frame_format_ = frame->format(); |
| + // TODO(penghuang): Support changing |frame_size_| & |frame_format_| more |
| + // than once. |
| + DCHECK(!frame_data_size_); |
| + frame_data_size_ = VideoFrame::AllocationSize(frame_format_, frame_size_); |
| + int32_t size = sizeof(ppapi::MediaStreamFrame::Video) + frame_data_size_; |
| + InitFrames(kNumberOfFrames, size); |
| + } |
| + |
| + int32_t index = frame_buffer()->DequeueFrame(); |
| + // Drop frames if the underlying buffer is empty. |
| + if (index < 0) |
| + return; |
| + |
| + ppapi::MediaStreamFrame::Video* ppframe = |
| + &(frame_buffer()->GetFramePointer(index)->video); |
| + ppframe->header.size = frame_buffer()->frame_size(); |
| + ppframe->header.type = ppapi::MediaStreamFrame::TYPE_VIDEO; |
| + ppframe->timestamp = frame->GetTimestamp().InSecondsF(); |
| + ppframe->format = ppformat; |
| + ppframe->size.width = frame->coded_size().width(); |
| + ppframe->size.height = frame->coded_size().height(); |
| + ppframe->data_size = frame_data_size_; |
| + |
| + COMPILE_ASSERT(VideoFrame::kYPlane == 0, y_plane_should_be_0); |
| + COMPILE_ASSERT(VideoFrame::kUPlane == 1, u_plane_should_be_1); |
| + COMPILE_ASSERT(VideoFrame::kVPlane == 2, v_plane_should_be_2); |
| + |
| + uint8_t* dst = ppframe->data; |
| + for (size_t i = 0; i < VideoFrame::NumPlanes(frame->format()); ++i) { |
|
dmichael (off chromium)
2014/01/09 21:06:47
It's a shame we have to do this copy stuff. It wou
Peng
2014/01/10 19:14:30
As my understanding, blink::MediaStreamTrack suppo
|
| + const uint8_t* src = frame->data(i); |
| + const size_t row_bytes = frame->row_bytes(i); |
| + const size_t src_stride = frame->stride(i); |
| + for (int j = 0; j < frame->rows(i); ++j) { |
| + memcpy(dst, src, row_bytes); |
| + dst += row_bytes; |
| + src += src_stride; |
| + } |
| + } |
| + PluginEnqueueFrame(index); |
| +} |
| + |
| +void PepperMediaStreamVideoTrackHost::DidConnectPendingHostToResource() { |
| + if (!connected_) { |
| + MediaStreamVideoSink::AddToVideoTrack(this, track_); |
| + connected_ = true; |
| + } |
| +} |
| + |
| +} // namespace content |