Commit 5e19b8ba authored by thembrown@gmail.com's avatar thembrown@gmail.com

Support configuring number of audio buffers in MediaStream Pepper API.

A optionally larger number of buffers makes recording audio in a pnacl module
more reliable when latency is not an issue.

BUG=330851

Review URL: https://codereview.chromium.org/290993005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@274511 0039d316-1c4b-4281-b951-d872f2087c98
parent b4b8711a
......@@ -223,6 +223,7 @@ Luke Zarko <lukezarko@gmail.com>
Maarten Lankhorst <m.b.lankhorst@gmail.com>
Magnus Danielsson <fuzzac@gmail.com>
Mahesh Kulkarni <mahesh.kk@samsung.com>
Manuel Braun <thembrown@gmail.com>
Mao Yujie <maojie0924@gmail.com>
Mao Yujie <yujie.mao@intel.com>
Marco Rodrigues <gothicx@gmail.com>
......
......@@ -4,24 +4,33 @@
#include "content/renderer/pepper/pepper_media_stream_audio_track_host.h"
#include <algorithm>
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/numerics/safe_math.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppb_audio_buffer.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/media_stream_audio_track_shared.h"
#include "ppapi/shared_impl/media_stream_buffer.h"
using media::AudioParameters;
using ppapi::host::HostMessageContext;
using ppapi::MediaStreamAudioTrackShared;
namespace {
// Max audio buffer duration in milliseconds.
const uint32_t kMaxDuration = 10;
// TODO(penghuang): make this configurable.
const int32_t kNumberOfBuffers = 4;
const int32_t kDefaultNumberOfBuffers = 4;
const int32_t kMaxNumberOfBuffers = 1000; // 10 sec
// Returns true if the |sample_rate| is supported in
// |PP_AudioBuffer_SampleRate|, otherwise false.
......@@ -57,7 +66,9 @@ PepperMediaStreamAudioTrackHost::AudioSink::AudioSink(
: host_(host),
buffer_data_size_(0),
main_message_loop_proxy_(base::MessageLoopProxy::current()),
weak_factory_(this) {}
weak_factory_(this),
number_of_buffers_(kDefaultNumberOfBuffers),
bytes_per_second_(0) {}
PepperMediaStreamAudioTrackHost::AudioSink::~AudioSink() {
DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
......@@ -71,15 +82,41 @@ void PepperMediaStreamAudioTrackHost::AudioSink::EnqueueBuffer(int32_t index) {
buffers_.push_back(index);
}
void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffersOnMainThread(
int32_t number_of_buffers,
int32_t buffer_size) {
void PepperMediaStreamAudioTrackHost::AudioSink::Configure(
int32_t number_of_buffers) {
DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
bool result = host_->InitBuffers(number_of_buffers, buffer_size, kRead);
bool changed = false;
if (number_of_buffers != number_of_buffers_)
changed = true;
number_of_buffers_ = number_of_buffers;
// Initialize later in OnSetFormat if bytes_per_second_ is not know yet.
if (changed && bytes_per_second_ > 0)
InitBuffers();
}
void PepperMediaStreamAudioTrackHost::AudioSink::SetFormatOnMainThread(
int bytes_per_second) {
bytes_per_second_ = bytes_per_second;
InitBuffers();
}
void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffers() {
DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
// The size is slightly bigger than necessary, because 8 extra bytes are
// added into the struct. Also see |MediaStreamBuffer|.
base::CheckedNumeric<int32_t> buffer_size = bytes_per_second_;
buffer_size *= kMaxDuration;
buffer_size /= base::Time::kMillisecondsPerSecond;
buffer_size += sizeof(ppapi::MediaStreamBuffer::Audio);
bool result = host_->InitBuffers(number_of_buffers_,
buffer_size.ValueOrDie(),
kRead);
// TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin.
CHECK(result);
base::AutoLock lock(lock_);
for (int32_t i = 0; i < number_of_buffers; ++i) {
buffers_.clear();
for (int32_t i = 0; i < number_of_buffers_; ++i) {
int32_t index = host_->buffer_manager()->DequeueBuffer();
DCHECK_GE(index, 0);
buffers_.push_back(index);
......@@ -154,18 +191,12 @@ void PepperMediaStreamAudioTrackHost::AudioSink::OnSetFormat(
} else {
audio_thread_checker_.DetachFromThread();
original_audio_params_ = params;
// The size is slightly bigger than necessary, because 8 extra bytes are
// added into the struct. Also see |MediaStreamBuffer|.
size_t max_data_size = params.sample_rate() * params.bits_per_sample() / 8 *
params.channels() * kMaxDuration / 1000;
size_t size = sizeof(ppapi::MediaStreamBuffer::Audio) + max_data_size;
main_message_loop_proxy_->PostTask(
FROM_HERE,
base::Bind(&AudioSink::InitBuffersOnMainThread,
base::Bind(&AudioSink::SetFormatOnMainThread,
weak_factory_.GetWeakPtr(),
kNumberOfBuffers,
static_cast<int32_t>(size)));
params.GetBytesPerSecond()));
}
}
......@@ -185,6 +216,32 @@ PepperMediaStreamAudioTrackHost::~PepperMediaStreamAudioTrackHost() {
OnClose();
}
int32_t PepperMediaStreamAudioTrackHost::OnResourceMessageReceived(
const IPC::Message& msg,
HostMessageContext* context) {
PPAPI_BEGIN_MESSAGE_MAP(PepperMediaStreamAudioTrackHost, msg)
PPAPI_DISPATCH_HOST_RESOURCE_CALL(
PpapiHostMsg_MediaStreamAudioTrack_Configure, OnHostMsgConfigure)
PPAPI_END_MESSAGE_MAP()
return PepperMediaStreamTrackHostBase::OnResourceMessageReceived(msg,
context);
}
int32_t PepperMediaStreamAudioTrackHost::OnHostMsgConfigure(
HostMessageContext* context,
const MediaStreamAudioTrackShared::Attributes& attributes) {
if (!MediaStreamAudioTrackShared::VerifyAttributes(attributes))
return PP_ERROR_BADARGUMENT;
int32_t buffers = attributes.buffers
? std::min(kMaxNumberOfBuffers, attributes.buffers)
: kDefaultNumberOfBuffers;
audio_sink_.Configure(buffers);
context->reply_msg = PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply();
return PP_OK;
}
void PepperMediaStreamAudioTrackHost::OnClose() {
if (connected_) {
MediaStreamAudioSink::RemoveFromAudioTrack(&audio_sink_, track_);
......
......@@ -15,6 +15,7 @@
#include "content/public/renderer/media_stream_audio_sink.h"
#include "content/renderer/pepper/pepper_media_stream_track_host_base.h"
#include "media/audio/audio_parameters.h"
#include "ppapi/shared_impl/media_stream_audio_track_shared.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
namespace base {
......@@ -43,10 +44,14 @@ class PepperMediaStreamAudioTrackHost : public PepperMediaStreamTrackHostBase {
// This function is called on the main thread.
void EnqueueBuffer(int32_t index);
// This function is called on the main thread.
void Configure(int32_t number_of_buffers);
private:
// Initializes buffers on the main thread.
void InitBuffersOnMainThread(int32_t number_of_buffers,
int32_t buffer_size);
void SetFormatOnMainThread(int bytes_per_second);
void InitBuffers();
// Send enqueue buffer message on the main thread.
void SendEnqueueBufferMessageOnMainThread(int32_t index);
......@@ -99,11 +104,27 @@ class PepperMediaStreamAudioTrackHost : public PepperMediaStreamTrackHostBase {
base::WeakPtrFactory<AudioSink> weak_factory_;
// Number of buffers.
int32_t number_of_buffers_;
// Number of bytes per second.
int bytes_per_second_;
DISALLOW_COPY_AND_ASSIGN(AudioSink);
};
virtual ~PepperMediaStreamAudioTrackHost();
// ResourceMessageHandler overrides:
virtual int32_t OnResourceMessageReceived(
const IPC::Message& msg,
ppapi::host::HostMessageContext* context) OVERRIDE;
// Message handlers:
int32_t OnHostMsgConfigure(
ppapi::host::HostMessageContext* context,
const ppapi::MediaStreamAudioTrackShared::Attributes& attributes);
// PepperMediaStreamTrackHostBase overrides:
virtual void OnClose() OVERRIDE;
......
......@@ -5,6 +5,7 @@
#include "content/renderer/pepper/pepper_media_stream_track_host_base.h"
#include "base/logging.h"
#include "base/numerics/safe_math.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/renderer_ppapi_host.h"
#include "ppapi/c/pp_errors.h"
......@@ -36,20 +37,26 @@ bool PepperMediaStreamTrackHostBase::InitBuffers(int32_t number_of_buffers,
DCHECK_GT(buffer_size,
static_cast<int32_t>(sizeof(ppapi::MediaStreamBuffer::Header)));
// Make each buffer 4 byte aligned.
buffer_size = (buffer_size + 3) & ~0x3;
base::CheckedNumeric<int32_t> buffer_size_aligned = buffer_size;
buffer_size_aligned += (4 - buffer_size % 4);
// TODO(penghuang): |HostAllocateSharedMemoryBuffer| uses sync IPC. We should
// avoid it.
int32_t size = number_of_buffers * buffer_size;
base::CheckedNumeric<int32_t> size = number_of_buffers * buffer_size_aligned;
if (!size.IsValid())
return false;
content::RenderThread* render_thread = content::RenderThread::Get();
scoped_ptr<base::SharedMemory> shm(
render_thread->HostAllocateSharedMemoryBuffer(size).Pass());
render_thread->HostAllocateSharedMemoryBuffer(size.ValueOrDie()).Pass());
if (!shm)
return false;
base::SharedMemoryHandle shm_handle = shm->handle();
if (!buffer_manager_.SetBuffers(
number_of_buffers, buffer_size, shm.Pass(), true)) {
if (!buffer_manager_.SetBuffers(number_of_buffers,
buffer_size_aligned.ValueOrDie(),
shm.Pass(),
true)) {
return false;
}
......@@ -62,12 +69,13 @@ bool PepperMediaStreamTrackHostBase::InitBuffers(int32_t number_of_buffers,
#error Not implemented.
#endif
SerializedHandle handle(host_->ShareHandleWithRemote(platform_file, false),
size);
size.ValueOrDie());
bool readonly = (track_type == kRead);
host()->SendUnsolicitedReplyWithHandles(
pp_resource(),
PpapiPluginMsg_MediaStreamTrack_InitBuffers(number_of_buffers,
buffer_size,
PpapiPluginMsg_MediaStreamTrack_InitBuffers(
number_of_buffers,
buffer_size_aligned.ValueOrDie(),
readonly),
std::vector<SerializedHandle>(1, handle));
return true;
......
......@@ -83,7 +83,8 @@ interface PPB_MediaStreamAudioTrack {
* the input buffers. If all buffers are filled, then samples will be
* dropped. The application can detect this by examining the timestamp on
* returned buffers. If <code>Configure()</code> is not called, default
* settings will be used.
* settings will be used. Calls to Configure while the plugin holds
* buffers will fail.
* Example usage from plugin code:
* @code
* int32_t attribs[] = {
......
......@@ -3,7 +3,7 @@
* found in the LICENSE file.
*/
/* From ppb_media_stream_audio_track.idl modified Fri Mar 28 10:13:34 2014. */
/* From ppb_media_stream_audio_track.idl modified Wed May 28 09:36:15 2014. */
#ifndef PPAPI_C_PPB_MEDIA_STREAM_AUDIO_TRACK_H_
#define PPAPI_C_PPB_MEDIA_STREAM_AUDIO_TRACK_H_
......@@ -98,7 +98,8 @@ struct PPB_MediaStreamAudioTrack_0_1 {
* the input buffers. If all buffers are filled, then samples will be
* dropped. The application can detect this by examining the timestamp on
* returned buffers. If <code>Configure()</code> is not called, default
* settings will be used.
* settings will be used. Calls to Configure while the plugin holds
* buffers will fail.
* Example usage from plugin code:
* @code
* int32_t attribs[] = {
......
......@@ -56,7 +56,8 @@ class MediaStreamAudioTrack : public Resource {
/// all input buffers. If all buffers are filled, then samples will be
/// dropped. The application can detect this by examining the timestamp on
/// returned buffers. If <code>Configure()</code> is not called, default
/// settings will be used.
/// settings will be used. Calls to Configure while the plugin holds
/// buffers will fail.
/// Example usage from plugin code:
/// @code
/// int32_t attribs[] = {
......
......@@ -42,8 +42,10 @@
'shared_impl/media_stream_buffer.h',
'shared_impl/media_stream_buffer_manager.cc',
'shared_impl/media_stream_buffer_manager.h',
'shared_impl/media_stream_video_track_shared.h',
'shared_impl/media_stream_audio_track_shared.cc',
'shared_impl/media_stream_audio_track_shared.h',
'shared_impl/media_stream_video_track_shared.cc',
'shared_impl/media_stream_video_track_shared.h',
'shared_impl/platform_file.cc',
'shared_impl/platform_file.h',
'shared_impl/ppapi_constants.h',
......
......@@ -177,6 +177,7 @@
'proxy/talk_resource_unittest.cc',
'proxy/video_decoder_resource_unittest.cc',
'proxy/websocket_resource_unittest.cc',
'shared_impl/media_stream_audio_track_shared_unittest.cc',
'shared_impl/media_stream_buffer_manager_unittest.cc',
'shared_impl/media_stream_video_track_shared_unittest.cc',
'shared_impl/proxy_lock_unittest.cc',
......
......@@ -5,6 +5,8 @@
#include "ppapi/proxy/media_stream_audio_track_resource.h"
#include "ppapi/proxy/audio_buffer_resource.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/media_stream_audio_track_shared.h"
#include "ppapi/shared_impl/media_stream_buffer.h"
#include "ppapi/shared_impl/var.h"
......@@ -41,8 +43,46 @@ PP_Bool MediaStreamAudioTrackResource::HasEnded() {
int32_t MediaStreamAudioTrackResource::Configure(
const int32_t attrib_list[],
scoped_refptr<TrackedCallback> callback) {
// TODO(penghuang): Implement this function.
if (has_ended())
return PP_ERROR_FAILED;
if (TrackedCallback::IsPending(configure_callback_) ||
TrackedCallback::IsPending(get_buffer_callback_)) {
return PP_ERROR_INPROGRESS;
}
// Do not support configure if audio buffers are held by plugin.
if (!buffers_.empty())
return PP_ERROR_INPROGRESS;
MediaStreamAudioTrackShared::Attributes attributes;
int i = 0;
for (; attrib_list[i] != PP_MEDIASTREAMAUDIOTRACK_ATTRIB_NONE; i += 2) {
switch (attrib_list[i]) {
case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_BUFFERS:
attributes.buffers = attrib_list[i + 1];
break;
case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_SAMPLE_RATE:
case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_SAMPLE_SIZE:
case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_CHANNELS:
case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_DURATION:
return PP_ERROR_NOTSUPPORTED;
default:
return PP_ERROR_BADARGUMENT;
}
}
if (!MediaStreamAudioTrackShared::VerifyAttributes(attributes))
return PP_ERROR_BADARGUMENT;
configure_callback_ = callback;
Call<PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply>(
RENDERER,
PpapiHostMsg_MediaStreamAudioTrack_Configure(attributes),
base::Bind(&MediaStreamAudioTrackResource::OnPluginMsgConfigureReply,
base::Unretained(this)),
callback);
return PP_OK_COMPLETIONPENDING;
}
int32_t MediaStreamAudioTrackResource::GetAttrib(
......@@ -58,7 +98,8 @@ int32_t MediaStreamAudioTrackResource::GetBuffer(
if (has_ended())
return PP_ERROR_FAILED;
if (TrackedCallback::IsPending(get_buffer_callback_))
if (TrackedCallback::IsPending(configure_callback_) ||
TrackedCallback::IsPending(get_buffer_callback_))
return PP_ERROR_INPROGRESS;
*buffer = GetAudioBuffer();
......@@ -144,5 +185,14 @@ void MediaStreamAudioTrackResource::ReleaseBuffers() {
}
}
void MediaStreamAudioTrackResource::OnPluginMsgConfigureReply(
const ResourceMessageReplyParams& params) {
if (TrackedCallback::IsPending(configure_callback_)) {
scoped_refptr<TrackedCallback> callback;
callback.swap(configure_callback_);
callback->Run(params.result());
}
}
} // namespace proxy
} // namespace ppapi
......@@ -6,6 +6,7 @@
#define PPAPI_PROXY_MEDIA_STREAM_AUDIO_TRACK_RESOURCE_H_
#include <map>
#include <string>
#include "base/memory/ref_counted.h"
#include "ppapi/proxy/media_stream_track_resource_base.h"
......@@ -53,12 +54,17 @@ class PPAPI_PROXY_EXPORT MediaStreamAudioTrackResource
void ReleaseBuffers();
// IPC message handlers.
void OnPluginMsgConfigureReply(const ResourceMessageReplyParams& params);
// Allocated buffer resources by |GetBuffer()|.
typedef std::map<PP_Resource, scoped_refptr<AudioBufferResource> > BufferMap;
BufferMap buffers_;
PP_Resource* get_buffer_output_;
scoped_refptr<TrackedCallback> configure_callback_;
scoped_refptr<TrackedCallback> get_buffer_callback_;
DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioTrackResource);
......
......@@ -63,6 +63,7 @@
#include "ppapi/shared_impl/file_growth.h"
#include "ppapi/shared_impl/file_path.h"
#include "ppapi/shared_impl/file_ref_create_info.h"
#include "ppapi/shared_impl/media_stream_audio_track_shared.h"
#include "ppapi/shared_impl/media_stream_video_track_shared.h"
#include "ppapi/shared_impl/ppapi_nacl_plugin_args.h"
#include "ppapi/shared_impl/ppapi_preferences.h"
......@@ -244,6 +245,10 @@ IPC_STRUCT_TRAITS_BEGIN(ppapi::FlashSiteSetting)
IPC_STRUCT_TRAITS_MEMBER(permission)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(ppapi::MediaStreamAudioTrackShared::Attributes)
IPC_STRUCT_TRAITS_MEMBER(buffers)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(ppapi::MediaStreamVideoTrackShared::Attributes)
IPC_STRUCT_TRAITS_MEMBER(buffers)
IPC_STRUCT_TRAITS_MEMBER(width)
......@@ -1444,6 +1449,10 @@ IPC_MESSAGE_CONTROL1(PpapiPluginMsg_IsolatedFileSystem_BrowserOpenReply,
// MediaStream -----------------------------------------------------------------
IPC_MESSAGE_CONTROL1(PpapiPluginMsg_MediaStreamAudioTrack_CreateFromPendingHost,
std::string /* track_id */)
IPC_MESSAGE_CONTROL1(
PpapiHostMsg_MediaStreamAudioTrack_Configure,
ppapi::MediaStreamAudioTrackShared::Attributes /* attributes */)
IPC_MESSAGE_CONTROL0(PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply)
IPC_MESSAGE_CONTROL1(PpapiPluginMsg_MediaStreamVideoTrack_CreateFromPendingHost,
std::string /* track_id */)
IPC_MESSAGE_CONTROL0(PpapiHostMsg_MediaStreamVideoTrack_Create)
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ppapi/shared_impl/media_stream_audio_track_shared.h"
namespace ppapi {
// static
bool MediaStreamAudioTrackShared::VerifyAttributes(
const Attributes& attributes) {
if (attributes.buffers < 0)
return false;
return true;
}
} // namespace ppapi
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PPAPI_SHARED_IMPL_MEDIA_STREAM_AUDIO_TRACK_SHARED_H_
#define PPAPI_SHARED_IMPL_MEDIA_STREAM_AUDIO_TRACK_SHARED_H_
#include "ppapi/c/ppb_audio_buffer.h"
#include "ppapi/shared_impl/ppapi_shared_export.h"
namespace ppapi {
class PPAPI_SHARED_EXPORT MediaStreamAudioTrackShared {
public:
struct Attributes {
Attributes() : buffers(0) {}
int32_t buffers;
};
static bool VerifyAttributes(const Attributes& attributes);
};
} // namespace ppapi
#endif // PPAPI_SHARED_IMPL_MEDIA_STREAM_AUDIO_TRACK_SHARED_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ppapi/shared_impl/media_stream_audio_track_shared.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace ppapi {
TEST(MediaStreamAudioTrackShared, Verify) {
{
MediaStreamAudioTrackShared::Attributes attributes;
EXPECT_TRUE(MediaStreamAudioTrackShared::VerifyAttributes(attributes));
}
// Verify buffers
{
MediaStreamAudioTrackShared::Attributes attributes;
attributes.buffers = 0;
EXPECT_TRUE(MediaStreamAudioTrackShared::VerifyAttributes(attributes));
attributes.buffers = 8;
EXPECT_TRUE(MediaStreamAudioTrackShared::VerifyAttributes(attributes));
attributes.buffers = 1024;
EXPECT_TRUE(MediaStreamAudioTrackShared::VerifyAttributes(attributes));
attributes.buffers = -1;
EXPECT_FALSE(MediaStreamAudioTrackShared::VerifyAttributes(attributes));
}
}
} // namespace ppapi
......@@ -18,6 +18,9 @@ REGISTER_TEST_CASE(MediaStreamAudioTrack);
namespace {
// Real max defined in
// content/renderer/pepper/pepper_media_stream_audio_track_host.cc.
const int32_t kMaxNumberOfBuffers = 1000;
const int32_t kTimes = 3;
const char kJSCode[] =
"function gotStream(stream) {"
......@@ -53,7 +56,7 @@ bool IsSampleRateValid(PP_AudioBuffer_SampleRate sample_rate) {
}
}
}
} // namespace
TestMediaStreamAudioTrack::TestMediaStreamAudioTrack(TestingInstance* instance)
: TestCase(instance),
......@@ -70,6 +73,7 @@ TestMediaStreamAudioTrack::~TestMediaStreamAudioTrack() {
void TestMediaStreamAudioTrack::RunTests(const std::string& filter) {
RUN_TEST(Create, filter);
RUN_TEST(GetBuffer, filter);
RUN_TEST(Configure, filter);
}
void TestMediaStreamAudioTrack::HandleMessage(const pp::Var& message) {
......@@ -140,3 +144,85 @@ std::string TestMediaStreamAudioTrack::TestGetBuffer() {
audio_track_ = pp::MediaStreamAudioTrack();
PASS();
}
std::string TestMediaStreamAudioTrack::TestConfigure() {
// Create a track.
instance_->EvalScript(kJSCode);
event_.Wait();
event_.Reset();
ASSERT_FALSE(audio_track_.is_null());
ASSERT_FALSE(audio_track_.HasEnded());
ASSERT_FALSE(audio_track_.GetId().empty());
PP_TimeDelta timestamp = 0.0;
// Configure number of buffers.
struct {
int32_t buffers;
int32_t expect_result;
} buffers[] = {
{ 8, PP_OK },
{ 100, PP_OK },
{ kMaxNumberOfBuffers, PP_OK },
{ -1, PP_ERROR_BADARGUMENT },
{ kMaxNumberOfBuffers + 1, PP_OK }, // Clipped to max value.
{ 0, PP_OK }, // Use default.
};
for (size_t i = 0; i < sizeof(buffers) / sizeof(buffers[0]); ++i) {
TestCompletionCallback cc_configure(instance_->pp_instance(), false);
int32_t attrib_list[] = {
PP_MEDIASTREAMAUDIOTRACK_ATTRIB_BUFFERS, buffers[i].buffers,
PP_MEDIASTREAMAUDIOTRACK_ATTRIB_NONE,
};
cc_configure.WaitForResult(
audio_track_.Configure(attrib_list, cc_configure.GetCallback()));
ASSERT_EQ(buffers[i].expect_result, cc_configure.result());
// Get some buffers. This should also succeed when configure fails.
for (int j = 0; j < kTimes; ++j) {
TestCompletionCallbackWithOutput<pp::AudioBuffer> cc_get_buffer(
instance_->pp_instance(), false);
cc_get_buffer.WaitForResult(
audio_track_.GetBuffer(cc_get_buffer.GetCallback()));
ASSERT_EQ(PP_OK, cc_get_buffer.result());
pp::AudioBuffer buffer = cc_get_buffer.output();
ASSERT_FALSE(buffer.is_null());
ASSERT_TRUE(IsSampleRateValid(buffer.GetSampleRate()));
ASSERT_EQ(buffer.GetSampleSize(), PP_AUDIOBUFFER_SAMPLESIZE_16_BITS);
ASSERT_GE(buffer.GetTimestamp(), timestamp);
timestamp = buffer.GetTimestamp();
ASSERT_GT(buffer.GetDataBufferSize(), 0U);
ASSERT_TRUE(buffer.GetDataBuffer() != NULL);
audio_track_.RecycleBuffer(buffer);
}
}
// Configure should fail while plugin holds buffers.
{
TestCompletionCallbackWithOutput<pp::AudioBuffer> cc_get_buffer(
instance_->pp_instance(), false);
cc_get_buffer.WaitForResult(
audio_track_.GetBuffer(cc_get_buffer.GetCallback()));
ASSERT_EQ(PP_OK, cc_get_buffer.result());
pp::AudioBuffer buffer = cc_get_buffer.output();
int32_t attrib_list[] = {
PP_MEDIASTREAMAUDIOTRACK_ATTRIB_BUFFERS, 0,
PP_MEDIASTREAMAUDIOTRACK_ATTRIB_NONE,
};
TestCompletionCallback cc_configure(instance_->pp_instance(), false);
cc_configure.WaitForResult(
audio_track_.Configure(attrib_list, cc_configure.GetCallback()));
ASSERT_EQ(PP_ERROR_INPROGRESS, cc_configure.result());
audio_track_.RecycleBuffer(buffer);
}
// Close the track.
audio_track_.Close();
ASSERT_TRUE(audio_track_.HasEnded());
audio_track_ = pp::MediaStreamAudioTrack();
PASS();
}
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PAPPI_TESTS_TEST_MEDIA_STREAM_AUDIO_TRACK_H_
#define PAPPI_TESTS_TEST_MEDIA_STREAM_AUDIO_TRACK_H_
#ifndef PPAPI_TESTS_TEST_MEDIA_STREAM_AUDIO_TRACK_H_
#define PPAPI_TESTS_TEST_MEDIA_STREAM_AUDIO_TRACK_H_
#include <string>
......@@ -26,10 +26,11 @@ class TestMediaStreamAudioTrack : public TestCase {
std::string TestCreate();
std::string TestGetBuffer();
std::string TestConfigure();
pp::MediaStreamAudioTrack audio_track_;
NestedEvent event_;
};
#endif // PAPPI_TESTS_TEST_MEDIA_STREAM_AUDIO_TRACK_H_
#endif // PPAPI_TESTS_TEST_MEDIA_STREAM_AUDIO_TRACK_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment