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_audio_track_resource.h"
7 #include "ppapi/proxy/audio_buffer_resource.h"
8 #include "ppapi/proxy/ppapi_messages.h"
9 #include "ppapi/shared_impl/media_stream_audio_track_shared.h"
10 #include "ppapi/shared_impl/media_stream_buffer.h"
11 #include "ppapi/shared_impl/var.h"
16 MediaStreamAudioTrackResource::MediaStreamAudioTrackResource(
17 Connection connection
,
19 int pending_renderer_id
,
20 const std::string
& id
)
21 : MediaStreamTrackResourceBase(
22 connection
, instance
, pending_renderer_id
, id
),
23 get_buffer_output_(NULL
) {
26 MediaStreamAudioTrackResource::~MediaStreamAudioTrackResource() {
30 thunk::PPB_MediaStreamAudioTrack_API
*
31 MediaStreamAudioTrackResource::AsPPB_MediaStreamAudioTrack_API() {
35 PP_Var
MediaStreamAudioTrackResource::GetId() {
36 return StringVar::StringToPPVar(id());
39 PP_Bool
MediaStreamAudioTrackResource::HasEnded() {
40 return PP_FromBool(has_ended());
43 int32_t MediaStreamAudioTrackResource::Configure(
44 const int32_t attrib_list
[],
45 scoped_refptr
<TrackedCallback
> callback
) {
47 return PP_ERROR_FAILED
;
49 if (TrackedCallback::IsPending(configure_callback_
) ||
50 TrackedCallback::IsPending(get_buffer_callback_
)) {
51 return PP_ERROR_INPROGRESS
;
54 // Do not support configure if audio buffers are held by plugin.
55 if (!buffers_
.empty())
56 return PP_ERROR_INPROGRESS
;
58 MediaStreamAudioTrackShared::Attributes attributes
;
60 for (; attrib_list
[i
] != PP_MEDIASTREAMAUDIOTRACK_ATTRIB_NONE
; i
+= 2) {
61 switch (attrib_list
[i
]) {
62 case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_BUFFERS
:
63 attributes
.buffers
= attrib_list
[i
+ 1];
65 case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_SAMPLE_RATE
:
66 case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_SAMPLE_SIZE
:
67 case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_CHANNELS
:
68 case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_DURATION
:
69 return PP_ERROR_NOTSUPPORTED
;
71 return PP_ERROR_BADARGUMENT
;
75 if (!MediaStreamAudioTrackShared::VerifyAttributes(attributes
))
76 return PP_ERROR_BADARGUMENT
;
78 configure_callback_
= callback
;
79 Call
<PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply
>(
81 PpapiHostMsg_MediaStreamAudioTrack_Configure(attributes
),
82 base::Bind(&MediaStreamAudioTrackResource::OnPluginMsgConfigureReply
,
83 base::Unretained(this)),
85 return PP_OK_COMPLETIONPENDING
;
88 int32_t MediaStreamAudioTrackResource::GetAttrib(
89 PP_MediaStreamAudioTrack_Attrib attrib
,
91 // TODO(penghuang): Implement this function.
92 return PP_ERROR_NOTSUPPORTED
;
95 int32_t MediaStreamAudioTrackResource::GetBuffer(
97 scoped_refptr
<TrackedCallback
> callback
) {
99 return PP_ERROR_FAILED
;
101 if (TrackedCallback::IsPending(configure_callback_
) ||
102 TrackedCallback::IsPending(get_buffer_callback_
))
103 return PP_ERROR_INPROGRESS
;
105 *buffer
= GetAudioBuffer();
109 // TODO(penghuang): Use the callback as hints to determine which thread will
110 // use the resource, so we could deliver buffers to the target thread directly
111 // for better performance.
112 get_buffer_output_
= buffer
;
113 get_buffer_callback_
= callback
;
114 return PP_OK_COMPLETIONPENDING
;
117 int32_t MediaStreamAudioTrackResource::RecycleBuffer(PP_Resource buffer
) {
118 BufferMap::iterator it
= buffers_
.find(buffer
);
119 if (it
== buffers_
.end())
120 return PP_ERROR_BADRESOURCE
;
122 scoped_refptr
<AudioBufferResource
> buffer_resource
= it
->second
;
128 DCHECK_GE(buffer_resource
->GetBufferIndex(), 0);
130 SendEnqueueBufferMessageToHost(buffer_resource
->GetBufferIndex());
131 buffer_resource
->Invalidate();
135 void MediaStreamAudioTrackResource::Close() {
139 if (TrackedCallback::IsPending(get_buffer_callback_
)) {
140 *get_buffer_output_
= 0;
141 get_buffer_callback_
->PostAbort();
142 get_buffer_callback_
= NULL
;
143 get_buffer_output_
= 0;
147 MediaStreamTrackResourceBase::CloseInternal();
150 void MediaStreamAudioTrackResource::OnNewBufferEnqueued() {
151 if (!TrackedCallback::IsPending(get_buffer_callback_
))
154 *get_buffer_output_
= GetAudioBuffer();
155 int32_t result
= *get_buffer_output_
? PP_OK
: PP_ERROR_FAILED
;
156 get_buffer_output_
= NULL
;
157 scoped_refptr
<TrackedCallback
> callback
;
158 callback
.swap(get_buffer_callback_
);
159 callback
->Run(result
);
162 PP_Resource
MediaStreamAudioTrackResource::GetAudioBuffer() {
163 int32_t index
= buffer_manager()->DequeueBuffer();
167 MediaStreamBuffer
* buffer
= buffer_manager()->GetBufferPointer(index
);
169 scoped_refptr
<AudioBufferResource
> resource
=
170 new AudioBufferResource(pp_instance(), index
, buffer
);
171 // Add |pp_resource()| and |resource| into |buffers_|.
172 // |buffers_| uses scoped_ptr<> to hold a ref of |resource|. It keeps the
174 buffers_
.insert(BufferMap::value_type(resource
->pp_resource(), resource
));
175 return resource
->GetReference();
178 void MediaStreamAudioTrackResource::ReleaseBuffers() {
179 for (BufferMap::iterator it
= buffers_
.begin(); it
!= buffers_
.end(); ++it
) {
180 // Just invalidate and release VideoBufferResorce, but keep PP_Resource.
181 // So plugin can still use |RecycleBuffer()|.
182 it
->second
->Invalidate();
187 void MediaStreamAudioTrackResource::OnPluginMsgConfigureReply(
188 const ResourceMessageReplyParams
& params
) {
189 if (TrackedCallback::IsPending(configure_callback_
)) {
190 scoped_refptr
<TrackedCallback
> callback
;
191 callback
.swap(configure_callback_
);
192 callback
->Run(params
.result());