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.
5 #include "ppapi/proxy/media_stream_video_track_resource.h"
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"
17 MediaStreamVideoTrackResource::MediaStreamVideoTrackResource(
18 Connection connection
,
20 int pending_renderer_id
,
21 const std::string
& id
)
22 : MediaStreamTrackResourceBase(
23 connection
, instance
, pending_renderer_id
, id
),
24 get_frame_output_(NULL
) {
27 MediaStreamVideoTrackResource::MediaStreamVideoTrackResource(
28 Connection connection
,
30 : MediaStreamTrackResourceBase(connection
, instance
),
31 get_frame_output_(NULL
) {
32 SendCreate(RENDERER
, PpapiHostMsg_MediaStreamVideoTrack_Create());
35 MediaStreamVideoTrackResource::~MediaStreamVideoTrackResource() {
39 thunk::PPB_MediaStreamVideoTrack_API
*
40 MediaStreamVideoTrackResource::AsPPB_MediaStreamVideoTrack_API() {
44 PP_Var
MediaStreamVideoTrackResource::GetId() {
45 return StringVar::StringToPPVar(id());
48 PP_Bool
MediaStreamVideoTrackResource::HasEnded() {
49 return PP_FromBool(has_ended());
52 int32_t MediaStreamVideoTrackResource::Configure(
53 const int32_t attrib_list
[],
54 scoped_refptr
<TrackedCallback
> callback
) {
56 return PP_ERROR_FAILED
;
58 if (TrackedCallback::IsPending(configure_callback_
) ||
59 TrackedCallback::IsPending(get_frame_callback_
)) {
60 return PP_ERROR_INPROGRESS
;
63 // Do not support configure, if frames are hold by plugin.
65 return PP_ERROR_INPROGRESS
;
67 MediaStreamVideoTrackShared::Attributes attributes
;
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];
74 case PP_MEDIASTREAMVIDEOTRACK_ATTRIB_WIDTH
:
75 attributes
.width
= attrib_list
[i
+ 1];
77 case PP_MEDIASTREAMVIDEOTRACK_ATTRIB_HEIGHT
:
78 attributes
.height
= attrib_list
[i
+ 1];
80 case PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT
:
81 attributes
.format
= static_cast<PP_VideoFrame_Format
>(attrib_list
[i
+ 1]);
84 return PP_ERROR_BADARGUMENT
;
88 if (!MediaStreamVideoTrackShared::VerifyAttributes(attributes
))
89 return PP_ERROR_BADARGUMENT
;
91 configure_callback_
= callback
;
92 Call
<PpapiPluginMsg_MediaStreamVideoTrack_ConfigureReply
>(
94 PpapiHostMsg_MediaStreamVideoTrack_Configure(attributes
),
95 base::Bind(&MediaStreamVideoTrackResource::OnPluginMsgConfigureReply
,
96 base::Unretained(this)),
98 return PP_OK_COMPLETIONPENDING
;
101 int32_t MediaStreamVideoTrackResource::GetAttrib(
102 PP_MediaStreamVideoTrack_Attrib attrib
,
104 // TODO(penghuang): implement this function.
105 return PP_ERROR_NOTSUPPORTED
;
108 int32_t MediaStreamVideoTrackResource::GetFrame(
110 scoped_refptr
<TrackedCallback
> callback
) {
112 return PP_ERROR_FAILED
;
114 if (TrackedCallback::IsPending(configure_callback_
) ||
115 TrackedCallback::IsPending(get_frame_callback_
)) {
116 return PP_ERROR_INPROGRESS
;
119 *frame
= GetVideoFrame();
123 get_frame_output_
= frame
;
124 get_frame_callback_
= callback
;
125 return PP_OK_COMPLETIONPENDING
;
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
;
133 scoped_refptr
<VideoFrameResource
> frame_resource
= it
->second
;
139 DCHECK_GE(frame_resource
->GetBufferIndex(), 0);
141 SendEnqueueBufferMessageToHost(frame_resource
->GetBufferIndex());
142 frame_resource
->Invalidate();
146 void MediaStreamVideoTrackResource::Close() {
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;
158 MediaStreamTrackResourceBase::CloseInternal();
161 int32_t MediaStreamVideoTrackResource::GetEmptyFrame(
162 PP_Resource
* frame
, scoped_refptr
<TrackedCallback
> callback
) {
163 return GetFrame(frame
, callback
);
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
);
172 void MediaStreamVideoTrackResource::OnNewBufferEnqueued() {
173 if (!TrackedCallback::IsPending(get_frame_callback_
))
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
);
184 PP_Resource
MediaStreamVideoTrackResource::GetVideoFrame() {
185 int32_t index
= buffer_manager()->DequeueBuffer();
189 MediaStreamBuffer
* buffer
= buffer_manager()->GetBufferPointer(index
);
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
196 frames_
.insert(FrameMap::value_type(resource
->pp_resource(), resource
));
197 return resource
->GetReference();
200 void MediaStreamVideoTrackResource::ReleaseFrames() {
201 for (FrameMap::iterator it
= frames_
.begin(); it
!= frames_
.end(); ++it
) {
202 // Just invalidate and release VideoFrameResorce, but keep PP_Resource.
203 // So plugin can still use |RecycleFrame()|.
204 it
->second
->Invalidate();
209 void MediaStreamVideoTrackResource::OnPluginMsgConfigureReply(
210 const ResourceMessageReplyParams
& params
,
211 const std::string
& track_id
) {
215 DCHECK_EQ(id(), track_id
);
217 if (TrackedCallback::IsPending(configure_callback_
)) {
218 scoped_refptr
<TrackedCallback
> callback
;
219 callback
.swap(configure_callback_
);
220 callback
->Run(params
.result());