Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / renderer / pepper / pepper_media_stream_video_track_host.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/renderer/pepper/pepper_media_stream_video_track_host.h"
6
7 #include "base/logging.h"
8 #include "ppapi/c/pp_errors.h"
9 #include "ppapi/c/ppb_video_frame.h"
10 #include "ppapi/shared_impl/media_stream_buffer.h"
11
12 using media::VideoFrame;
13
14 namespace {
15
16 // TODO(penghuang): make it configurable.
17 const int32_t kNumberOfFrames = 4;
18
19 PP_VideoFrame_Format ToPpapiFormat(VideoFrame::Format format) {
20   switch (format) {
21     case VideoFrame::YV12:
22       return PP_VIDEOFRAME_FORMAT_YV12;
23     case VideoFrame::YV16:
24       return PP_VIDEOFRAME_FORMAT_YV16;
25     case VideoFrame::I420:
26       return PP_VIDEOFRAME_FORMAT_I420;
27     case VideoFrame::YV12A:
28       return PP_VIDEOFRAME_FORMAT_YV12A;
29     case VideoFrame::YV12J:
30       return PP_VIDEOFRAME_FORMAT_YV12J;
31     default:
32       DVLOG(1) << "Unsupported pixel format " << format;
33       return PP_VIDEOFRAME_FORMAT_UNKNOWN;
34   }
35 }
36
37 }  // namespace
38
39 namespace content {
40
41 PepperMediaStreamVideoTrackHost::PepperMediaStreamVideoTrackHost(
42     RendererPpapiHost* host,
43     PP_Instance instance,
44     PP_Resource resource,
45     const blink::WebMediaStreamTrack& track)
46     : PepperMediaStreamTrackHostBase(host, instance, resource),
47       track_(track),
48       connected_(false),
49       frame_format_(VideoFrame::UNKNOWN),
50       frame_data_size_(0) {
51   DCHECK(!track_.isNull());
52 }
53
54 PepperMediaStreamVideoTrackHost::~PepperMediaStreamVideoTrackHost() {
55   OnClose();
56 }
57
58 void PepperMediaStreamVideoTrackHost::OnClose() {
59   if (connected_) {
60     MediaStreamVideoSink::RemoveFromVideoTrack(this, track_);
61     connected_ = false;
62   }
63 }
64
65 void PepperMediaStreamVideoTrackHost::OnVideoFrame(
66     const scoped_refptr<VideoFrame>& frame) {
67   DCHECK(frame);
68   // TODO(penghuang): Check |frame->end_of_stream()| and close the track.
69   PP_VideoFrame_Format ppformat = ToPpapiFormat(frame->format());
70   if (ppformat == PP_VIDEOFRAME_FORMAT_UNKNOWN)
71     return;
72
73   if (frame_size_ != frame->coded_size() || frame_format_ != frame->format()) {
74     frame_size_ = frame->coded_size();
75     frame_format_ = frame->format();
76     // TODO(penghuang): Support changing |frame_size_| & |frame_format_| more
77     // than once.
78     DCHECK(!frame_data_size_);
79     frame_data_size_ = VideoFrame::AllocationSize(frame_format_, frame_size_);
80     int32_t size = sizeof(ppapi::MediaStreamBuffer::Video) + frame_data_size_;
81     bool result = InitBuffers(kNumberOfFrames, size);
82     // TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin.
83     CHECK(result);
84   }
85
86   int32_t index = buffer_manager()->DequeueBuffer();
87   // Drop frames if the underlying buffer is full.
88   if (index < 0)
89     return;
90
91   // TODO(penghuang): support format conversion and size scaling.
92   ppapi::MediaStreamBuffer::Video* buffer =
93       &(buffer_manager()->GetBufferPointer(index)->video);
94   buffer->header.size = buffer_manager()->buffer_size();
95   buffer->header.type = ppapi::MediaStreamBuffer::TYPE_VIDEO;
96   buffer->timestamp = frame->GetTimestamp().InSecondsF();
97   buffer->format = ppformat;
98   buffer->size.width = frame->coded_size().width();
99   buffer->size.height = frame->coded_size().height();
100   buffer->data_size = frame_data_size_;
101
102   COMPILE_ASSERT(VideoFrame::kYPlane == 0, y_plane_should_be_0);
103   COMPILE_ASSERT(VideoFrame::kUPlane == 1, u_plane_should_be_1);
104   COMPILE_ASSERT(VideoFrame::kVPlane == 2, v_plane_should_be_2);
105
106   uint8_t* dst = buffer->data;
107   size_t num_planes = VideoFrame::NumPlanes(frame->format());
108   for (size_t i = 0; i < num_planes; ++i) {
109     const uint8_t* src = frame->data(i);
110     const size_t row_bytes = frame->row_bytes(i);
111     const size_t src_stride = frame->stride(i);
112     int rows = frame->rows(i);
113     for (int j = 0; j < rows; ++j) {
114       memcpy(dst, src, row_bytes);
115       dst += row_bytes;
116       src += src_stride;
117     }
118   }
119
120   SendEnqueueBufferMessageToPlugin(index);
121 }
122
123 void PepperMediaStreamVideoTrackHost::DidConnectPendingHostToResource() {
124   if (!connected_) {
125     MediaStreamVideoSink::AddToVideoTrack(this, track_);
126     connected_ = true;
127   }
128 }
129
130 }  // namespace content