media_stream_audio_track_resource.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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_audio_track_resource.h"
6
7#include "ppapi/proxy/audio_buffer_resource.h"
8#include "ppapi/shared_impl/media_stream_buffer.h"
9#include "ppapi/shared_impl/var.h"
10
11namespace ppapi {
12namespace proxy {
13
14MediaStreamAudioTrackResource::MediaStreamAudioTrackResource(
15    Connection connection,
16    PP_Instance instance,
17    int pending_renderer_id,
18    const std::string& id)
19    : MediaStreamTrackResourceBase(
20        connection, instance, pending_renderer_id, id),
21      get_buffer_output_(NULL) {
22}
23
24MediaStreamAudioTrackResource::~MediaStreamAudioTrackResource() {
25  Close();
26}
27
28thunk::PPB_MediaStreamAudioTrack_API*
29MediaStreamAudioTrackResource::AsPPB_MediaStreamAudioTrack_API() {
30  return this;
31}
32
33PP_Var MediaStreamAudioTrackResource::GetId() {
34  return StringVar::StringToPPVar(id());
35}
36
37PP_Bool MediaStreamAudioTrackResource::HasEnded() {
38  return PP_FromBool(has_ended());
39}
40
41int32_t MediaStreamAudioTrackResource::Configure(
42    const int32_t attrib_list[],
43    scoped_refptr<TrackedCallback> callback) {
44  // TODO(penghuang): Implement this function.
45  return PP_ERROR_NOTSUPPORTED;
46}
47
48int32_t MediaStreamAudioTrackResource::GetAttrib(
49    PP_MediaStreamAudioTrack_Attrib attrib,
50    int32_t* value) {
51  // TODO(penghuang): Implement this function.
52  return PP_ERROR_NOTSUPPORTED;
53}
54
55int32_t MediaStreamAudioTrackResource::GetBuffer(
56    PP_Resource* buffer,
57    scoped_refptr<TrackedCallback> callback) {
58  if (has_ended())
59    return PP_ERROR_FAILED;
60
61  if (TrackedCallback::IsPending(get_buffer_callback_))
62    return PP_ERROR_INPROGRESS;
63
64  *buffer = GetAudioBuffer();
65  if (*buffer)
66    return PP_OK;
67
68  // TODO(penghuang): Use the callback as hints to determine which thread will
69  // use the resource, so we could deliver buffers to the target thread directly
70  // for better performance.
71  get_buffer_output_ = buffer;
72  get_buffer_callback_ = callback;
73  return PP_OK_COMPLETIONPENDING;
74}
75
76int32_t MediaStreamAudioTrackResource::RecycleBuffer(PP_Resource buffer) {
77  BufferMap::iterator it = buffers_.find(buffer);
78  if (it == buffers_.end())
79    return PP_ERROR_BADRESOURCE;
80
81  scoped_refptr<AudioBufferResource> buffer_resource = it->second;
82  buffers_.erase(it);
83
84  if (has_ended())
85    return PP_OK;
86
87  DCHECK_GE(buffer_resource->GetBufferIndex(), 0);
88
89  SendEnqueueBufferMessageToHost(buffer_resource->GetBufferIndex());
90  buffer_resource->Invalidate();
91  return PP_OK;
92}
93
94void MediaStreamAudioTrackResource::Close() {
95  if (has_ended())
96    return;
97
98  if (TrackedCallback::IsPending(get_buffer_callback_)) {
99    *get_buffer_output_ = 0;
100    get_buffer_callback_->PostAbort();
101    get_buffer_callback_ = NULL;
102    get_buffer_output_ = 0;
103  }
104
105  ReleaseBuffers();
106  MediaStreamTrackResourceBase::CloseInternal();
107}
108
109void MediaStreamAudioTrackResource::OnNewBufferEnqueued() {
110  if (!TrackedCallback::IsPending(get_buffer_callback_))
111    return;
112
113  *get_buffer_output_ = GetAudioBuffer();
114  int32_t result = *get_buffer_output_ ? PP_OK : PP_ERROR_FAILED;
115  get_buffer_output_ = NULL;
116  scoped_refptr<TrackedCallback> callback;
117  callback.swap(get_buffer_callback_);
118  callback->Run(result);
119}
120
121PP_Resource MediaStreamAudioTrackResource::GetAudioBuffer() {
122  int32_t index = buffer_manager()->DequeueBuffer();
123  if (index < 0)
124      return 0;
125
126  MediaStreamBuffer* buffer = buffer_manager()->GetBufferPointer(index);
127  DCHECK(buffer);
128  scoped_refptr<AudioBufferResource> resource =
129      new AudioBufferResource(pp_instance(), index, buffer);
130  // Add |pp_resource()| and |resource| into |buffers_|.
131  // |buffers_| uses scoped_ptr<> to hold a ref of |resource|. It keeps the
132  // resource alive.
133  buffers_.insert(BufferMap::value_type(resource->pp_resource(), resource));
134  return resource->GetReference();
135}
136
137void MediaStreamAudioTrackResource::ReleaseBuffers() {
138  BufferMap::iterator it = buffers_.begin();
139  while (it != buffers_.end()) {
140    // Just invalidate and release VideoBufferResorce, but keep PP_Resource.
141    // So plugin can still use |RecycleBuffer()|.
142    it->second->Invalidate();
143    it->second = NULL;
144  }
145}
146
147}  // namespace proxy
148}  // namespace ppapi
149