Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ppapi / proxy / media_stream_video_track_resource.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 "ppapi/proxy/media_stream_video_track_resource.h"
6
7 #include "base/logging.h"
8 #include "ppapi/proxy/ppapi_messages.h"
9 #include "ppapi/proxy/video_frame_resource.h"
10 #include "ppapi/shared_impl/media_stream_buffer.h"
11 #include "ppapi/shared_impl/media_stream_video_track_shared.h"
12 #include "ppapi/shared_impl/var.h"
13
14 namespace ppapi {
15 namespace proxy {
16
17 MediaStreamVideoTrackResource::MediaStreamVideoTrackResource(
18     Connection connection,
19     PP_Instance instance,
20     int pending_renderer_id,
21     const std::string& id)
22     : MediaStreamTrackResourceBase(
23         connection, instance, pending_renderer_id, id),
24       get_frame_output_(NULL) {
25 }
26
27 MediaStreamVideoTrackResource::MediaStreamVideoTrackResource(
28     Connection connection,
29     PP_Instance instance)
30     : MediaStreamTrackResourceBase(connection, instance),
31       get_frame_output_(NULL) {
32   SendCreate(RENDERER, PpapiHostMsg_MediaStreamVideoTrack_Create());
33 }
34
35 MediaStreamVideoTrackResource::~MediaStreamVideoTrackResource() {
36   Close();
37 }
38
39 thunk::PPB_MediaStreamVideoTrack_API*
40 MediaStreamVideoTrackResource::AsPPB_MediaStreamVideoTrack_API() {
41   return this;
42 }
43
44 PP_Var MediaStreamVideoTrackResource::GetId() {
45   return StringVar::StringToPPVar(id());
46 }
47
48 PP_Bool MediaStreamVideoTrackResource::HasEnded() {
49   return PP_FromBool(has_ended());
50 }
51
52 int32_t MediaStreamVideoTrackResource::Configure(
53     const int32_t attrib_list[],
54     scoped_refptr<TrackedCallback> callback) {
55   if (has_ended())
56     return PP_ERROR_FAILED;
57
58   if (TrackedCallback::IsPending(configure_callback_) ||
59       TrackedCallback::IsPending(get_frame_callback_)) {
60     return PP_ERROR_INPROGRESS;
61   }
62
63   // Do not support configure, if frames are hold by plugin.
64   if (!frames_.empty())
65     return PP_ERROR_INPROGRESS;
66
67   MediaStreamVideoTrackShared::Attributes attributes;
68   int i = 0;
69   for (;attrib_list[i] != PP_MEDIASTREAMVIDEOTRACK_ATTRIB_NONE; i += 2) {
70     switch (attrib_list[i]) {
71     case PP_MEDIASTREAMVIDEOTRACK_ATTRIB_BUFFERED_FRAMES:
72       attributes.buffers = attrib_list[i + 1];
73       break;
74     case PP_MEDIASTREAMVIDEOTRACK_ATTRIB_WIDTH:
75       attributes.width = attrib_list[i + 1];
76       break;
77     case PP_MEDIASTREAMVIDEOTRACK_ATTRIB_HEIGHT:
78       attributes.height = attrib_list[i + 1];
79       break;
80     case PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT:
81       attributes.format = static_cast<PP_VideoFrame_Format>(attrib_list[i + 1]);
82       break;
83     default:
84       return PP_ERROR_BADARGUMENT;
85     }
86   }
87
88   if (!MediaStreamVideoTrackShared::VerifyAttributes(attributes))
89     return PP_ERROR_BADARGUMENT;
90
91   configure_callback_ = callback;
92   Call<PpapiPluginMsg_MediaStreamVideoTrack_ConfigureReply>(
93       RENDERER,
94       PpapiHostMsg_MediaStreamVideoTrack_Configure(attributes),
95       base::Bind(&MediaStreamVideoTrackResource::OnPluginMsgConfigureReply,
96                  base::Unretained(this)),
97       callback);
98   return PP_OK_COMPLETIONPENDING;
99 }
100
101 int32_t MediaStreamVideoTrackResource::GetAttrib(
102     PP_MediaStreamVideoTrack_Attrib attrib,
103     int32_t* value) {
104   // TODO(penghuang): implement this function.
105   return PP_ERROR_NOTSUPPORTED;
106 }
107
108 int32_t MediaStreamVideoTrackResource::GetFrame(
109     PP_Resource* frame,
110     scoped_refptr<TrackedCallback> callback) {
111   if (has_ended())
112     return PP_ERROR_FAILED;
113
114   if (TrackedCallback::IsPending(configure_callback_) ||
115       TrackedCallback::IsPending(get_frame_callback_)) {
116     return PP_ERROR_INPROGRESS;
117   }
118
119   *frame = GetVideoFrame();
120   if (*frame)
121     return PP_OK;
122
123   get_frame_output_ = frame;
124   get_frame_callback_ = callback;
125   return PP_OK_COMPLETIONPENDING;
126 }
127
128 int32_t MediaStreamVideoTrackResource::RecycleFrame(PP_Resource frame) {
129   FrameMap::iterator it = frames_.find(frame);
130   if (it == frames_.end())
131     return PP_ERROR_BADRESOURCE;
132
133   scoped_refptr<VideoFrameResource> frame_resource = it->second;
134   frames_.erase(it);
135
136   if (has_ended())
137     return PP_OK;
138
139   DCHECK_GE(frame_resource->GetBufferIndex(), 0);
140
141   SendEnqueueBufferMessageToHost(frame_resource->GetBufferIndex());
142   frame_resource->Invalidate();
143   return PP_OK;
144 }
145
146 void MediaStreamVideoTrackResource::Close() {
147   if (has_ended())
148     return;
149
150   if (TrackedCallback::IsPending(get_frame_callback_)) {
151     *get_frame_output_ = 0;
152     get_frame_callback_->PostAbort();
153     get_frame_callback_ = NULL;
154     get_frame_output_ = 0;
155   }
156
157   ReleaseFrames();
158   MediaStreamTrackResourceBase::CloseInternal();
159 }
160
161 int32_t MediaStreamVideoTrackResource::GetEmptyFrame(
162     PP_Resource* frame, scoped_refptr<TrackedCallback> callback) {
163   return GetFrame(frame, callback);
164 }
165
166 int32_t MediaStreamVideoTrackResource::PutFrame(PP_Resource frame) {
167   // TODO(ronghuawu): Consider to rename RecycleFrame to PutFrame and use
168   // one set of GetFrame and PutFrame for both input and output.
169   return RecycleFrame(frame);
170 }
171
172 void MediaStreamVideoTrackResource::OnNewBufferEnqueued() {
173   if (!TrackedCallback::IsPending(get_frame_callback_))
174     return;
175
176   *get_frame_output_ = GetVideoFrame();
177   int32_t result = *get_frame_output_ ? PP_OK : PP_ERROR_FAILED;
178   get_frame_output_ = NULL;
179   scoped_refptr<TrackedCallback> callback;
180   callback.swap(get_frame_callback_);
181   callback->Run(result);
182 }
183
184 PP_Resource MediaStreamVideoTrackResource::GetVideoFrame() {
185   int32_t index = buffer_manager()->DequeueBuffer();
186   if (index < 0)
187     return 0;
188
189   MediaStreamBuffer* buffer = buffer_manager()->GetBufferPointer(index);
190   DCHECK(buffer);
191   scoped_refptr<VideoFrameResource> resource =
192       new VideoFrameResource(pp_instance(), index, buffer);
193   // Add |pp_resource()| and |resource| into |frames_|.
194   // |frames_| uses scoped_ptr<> to hold a ref of |resource|. It keeps the
195   // resource alive.
196   frames_.insert(FrameMap::value_type(resource->pp_resource(), resource));
197   return resource->GetReference();
198 }
199
200 void MediaStreamVideoTrackResource::ReleaseFrames() {
201   FrameMap::iterator it = frames_.begin();
202   while (it != frames_.end()) {
203     // Just invalidate and release VideoFrameResorce, but keep PP_Resource.
204     // So plugin can still use |RecycleFrame()|.
205     it->second->Invalidate();
206     it->second = NULL;
207   }
208 }
209
210 void MediaStreamVideoTrackResource::OnPluginMsgConfigureReply(
211     const ResourceMessageReplyParams& params,
212     const std::string& track_id) {
213   if (id().empty()) {
214     set_id(track_id);
215   } else {
216     DCHECK_EQ(id(), track_id);
217   }
218   if (TrackedCallback::IsPending(configure_callback_)) {
219     scoped_refptr<TrackedCallback> callback;
220     callback.swap(configure_callback_);
221     callback->Run(params.result());
222   }
223 }
224
225 }  // namespace proxy
226 }  // namespace ppapi