],
}, # capi-media-tool
{
+ 'target_name': 'mm-player',
+ 'type': 'none',
+ 'conditions': [
+ ['building_for_tizen==1', {
+ 'direct_dependent_settings': {
+ 'cflags': [
+ '<!@(<(pkg-config) --cflags mm-player)',
+ ],
+ },
+ 'link_settings': {
+ 'ldflags': [
+ '<!@(<(pkg-config) --libs-only-L --libs-only-other mm-player)',
+ ],
+ 'libraries': [
+ '<!@(<(pkg-config) --libs-only-l mm-player)',
+ ],
+ },
+ }],
+ ],
+ }, # mm-player
+ {
'target_name': 'tts',
'type': 'none',
'conditions': [
#define IPC_MESSAGE_START ChromeMsgStart
#if defined(TIZEN_MULTIMEDIA_SUPPORT)
-// This message runs the GStreamer for decoding audio for webaudio.
-IPC_MESSAGE_CONTROL3(EflViewHostMsg_GstWebAudioDecode,
+// This message runs audio decoding for webaudio.
+IPC_MESSAGE_CONTROL3(EflViewHostMsg_WebAudioDecode,
base::SharedMemoryHandle /* encoded_data_handle */,
base::FileDescriptor /* pcm_output */,
uint32_t /* data_size*/)
'sources': [
'browser/media/media_web_contents_observer_efl.cc',
'browser/media/media_web_contents_observer_efl.h',
- 'browser/media/efl/webaudio_decoder_browser_gstreamer.cc',
- 'browser/media/efl/webaudio_decoder_browser_gstreamer.h',
'browser/media/efl/browser_demuxer_efl.cc',
'browser/media/efl/browser_demuxer_efl.h',
'browser/media/efl/browser_media_player_manager_efl.cc',
[ 'exclude', 'renderer/media/audio_decoder\\.(cc|h)$' ],
],
'sources': [
+ 'renderer/media/efl/audio_decoder_efl.h',
'renderer/media/efl/audio_decoder_gstreamer.cc',
- 'renderer/media/efl/audio_decoder_gstreamer.h',
'renderer/media/efl/media_source_delegate_efl.cc',
'renderer/media/efl/media_source_delegate_efl.h',
'renderer/media/efl/renderer_demuxer_efl.cc',
'renderer/media/efl/webmediaplayer_efl.cc',
'renderer/media/efl/webmediaplayer_efl.h', # ME and MSE
],
+ 'conditions': [
+ ['tizen_multimedia_use_capi_for_me==1', {
+ 'sources': [
+ 'renderer/media/tizen/audio_decoder_capi.cc',
+ ],
+ 'sources!': [
+ 'renderer/media/efl/audio_decoder_gstreamer.cc',
+ ],
+ }],
+ ],
}], # tizen_multimedia_support==1
],
}
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_RENDERER_MEDIA_EFL_AUDIO_DECODER_GSTREAMER_H_
-#define CONTENT_RENDERER_MEDIA_EFL_AUDIO_DECODER_GSTREAMER_H_
+#ifndef CONTENT_RENDERER_MEDIA_EFL_AUDIO_DECODER_EFL_H_
+#define CONTENT_RENDERER_MEDIA_EFL_AUDIO_DECODER_EFL_H_
#include "content/renderer/media/android/audio_decoder_android.h"
-#endif // CONTENT_RENDERER_MEDIA_EFL_AUDIO_DECODER_GSTREAMER_H_
\ No newline at end of file
+#endif // CONTENT_RENDERER_MEDIA_EFL_AUDIO_DECODER_EFL_H_
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/renderer/media/efl/audio_decoder_gstreamer.h"
+#include "content/renderer/media/efl/audio_decoder_efl.h"
#include "base/basictypes.h"
#include "base/memory/shared_memory.h"
#include "media/base/efl/webaudio_media_codec_info_efl.h"
namespace content {
-//This class is similar as AudioDecoderIO class of Android defined
-//in src/content/renderer/media/android/audio_decoder_android.cc
+// This class is similar as AudioDecoderIO class of Android defined
+// in src/content/renderer/media/android/audio_decoder_android.cc
class AudioDecoderIO {
public:
AudioDecoderIO(const char* data, size_t data_size);
// encoded_data_handle for our shared memory and write the decoded
// PCM samples (16-bit integer) to our pipe.
- sender->Send(new EflViewHostMsg_GstWebAudioDecode(encoded_data_handle, fd, data_size));
+ sender->Send(new EflViewHostMsg_WebAudioDecode(encoded_data_handle,
+ fd, data_size));
int input_fd = audio_decoder.read_fd();
struct media::WebAudioMediaCodecInfoEfl info;
return false;
}
- unsigned number_of_channels = info.channel_count;
- double file_sample_rate = static_cast<double>(info.sample_rate);
- size_t number_of_frames = info.number_of_frames;
+ double file_sample_rate = static_cast<double>(info.sample_rate_);
// Sanity checks
- if (!number_of_channels ||
- number_of_channels > media::limits::kMaxChannels ||
+ if (!info.channel_count_ ||
+ info.channel_count_ > media::limits::kMaxChannels ||
file_sample_rate < media::limits::kMinSampleRate ||
file_sample_rate > media::limits::kMaxSampleRate) {
return false;
}
- if (number_of_frames > 0) {
+ if (info.number_of_frames_ > 0) {
CopyPcmDataToBus(input_fd,
destination_bus,
- number_of_frames,
- number_of_channels,
+ info.number_of_frames_,
+ info.channel_count_,
file_sample_rate);
} else {
BufferAndCopyPcmDataToBus(input_fd,
destination_bus,
- number_of_channels,
+ info.channel_count_,
file_sample_rate);
}
--- /dev/null
+// Copyright 2015 Samsung Electronics Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/efl/audio_decoder_efl.h"
+
+#include "base/basictypes.h"
+#include "base/memory/shared_memory.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/process/process.h"
+#include "base/strings/string_util.h"
+#include "base/time/time.h"
+#include "content/common/render_messages_efl.h"
+#include "media/base/audio_bus.h"
+#include "media/base/efl/webaudio_media_codec_info_efl.h"
+#include "media/base/limits.h"
+#include "public/platform/Platform.h"
+#include "third_party/WebKit/public/platform/WebAudioBus.h"
+
+namespace content {
+
+const size_t kAudioDataSizeLimit = 0x80000000;
+
+class AudioDecoderIO {
+ public:
+ AudioDecoderIO(const char* data, size_t data_size);
+ virtual ~AudioDecoderIO();
+ bool ShareEncodedDataToProcess(base::SharedMemoryHandle* handle);
+
+ // Returns true if |AudioDecoderIO| was successfully created.
+ bool IsValid() const;
+
+ int GetReadFd() const { return read_fd_; }
+ int GetWriteFd() const { return write_fd_; }
+
+ private:
+ // Shared memory that will hold the encoded audio data. This is
+ // used by |MediaCodec| for decoding.
+ base::SharedMemory encoded_data_handle_;
+
+ // A pipe used to communicate with MediaCodec. MediaCodec owns
+ // write_fd_ and writes to it.
+ int read_fd_;
+ int write_fd_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioDecoderIO);
+};
+
+AudioDecoderIO::AudioDecoderIO(const char* data, size_t data_size)
+ : read_fd_(-1), write_fd_(-1) {
+ if (!data || data_size > kAudioDataSizeLimit || data_size <= 0) {
+ LOG(ERROR) << " Invalid Data";
+ return;
+ }
+
+ // Create the shared memory and copy our data to it so that
+ // |MediaCodec| can access it.
+ if(!encoded_data_handle_.CreateAndMapAnonymous(data_size)) {
+ LOG(ERROR) << " Creation of shared memory failed";
+ return;
+ }
+
+ if (!encoded_data_handle_.memory()) {
+ LOG(ERROR) << " Invalid shared memory";
+ return;
+ }
+
+ memcpy(encoded_data_handle_.memory(), data, data_size);
+
+ // Create a pipe for reading/writing the decoded PCM data
+ int pipefd[2] = {0};
+ if (-1 == pipe(pipefd)) {
+ LOG(INFO) <<" Pipe is already created";
+ return;
+ }
+
+ read_fd_ = pipefd[0];
+ write_fd_ = pipefd[1];
+}
+
+AudioDecoderIO::~AudioDecoderIO() {
+ // Close the read end of the pipe. The write end should have been
+ // closed by |MediaCodec|.
+ if (read_fd_ >= 0 && close(read_fd_)) {
+ LOG(WARNING) << "Cannot close read fd " << read_fd_
+ << ": " << strerror(errno);
+ }
+ read_fd_ = -1;
+ write_fd_ = -1;
+}
+
+bool AudioDecoderIO::IsValid() const {
+ return read_fd_ >= 0 && write_fd_ >= 0 &&
+ encoded_data_handle_.memory();
+}
+
+bool AudioDecoderIO::ShareEncodedDataToProcess(
+ base::SharedMemoryHandle* handle) {
+ return encoded_data_handle_.ShareToProcess(base::GetCurrentProcessHandle(),
+ handle);
+}
+
+static void CopyPcmDataToBus(int input_fd,
+ blink::WebAudioBus* destination_bus,
+ size_t num_of_frames,
+ unsigned number_of_channels,
+ double file_sample_rate) {
+
+ ssize_t lread = 0;
+ float sample = 0;
+ size_t samples_in_pipe = 0;
+ struct media::WebAudioMediaDataInfoEfl data_info;
+ std::vector<float> decoded_samples[number_of_channels];
+ while ((lread =
+ HANDLE_EINTR(read(input_fd, &data_info, sizeof(data_info)))) > 0) {
+ float pipe_data[data_info.size_ / sizeof(float)];
+
+ lread = HANDLE_EINTR(read(input_fd, pipe_data, sizeof(pipe_data)));
+ samples_in_pipe = lread / sizeof(float);
+
+ for (int i = 0; i < number_of_channels; i++) {
+ if ((decoded_samples[i].size() + samples_in_pipe) >
+ decoded_samples[i].capacity()) {
+ decoded_samples[i].reserve(
+ std::max(samples_in_pipe, 2 * decoded_samples[i].capacity()));
+ }
+ }
+ std::copy(pipe_data, pipe_data + samples_in_pipe,
+ back_inserter(decoded_samples[data_info.channel_mask_ - 1]));
+ }
+ size_t number_of_samples = 0;
+ for (int i = 0; i < number_of_channels; i++) {
+ number_of_samples += decoded_samples[i].size();
+ }
+ size_t number_of_frames = number_of_samples / number_of_channels;
+ size_t decoded_frames = 0;
+ destination_bus->initialize(number_of_channels,
+ number_of_frames,
+ file_sample_rate);
+
+ for (size_t frames = 0; frames < number_of_frames; frames++) {
+ for (size_t channel = 0; channel < number_of_channels; channel++) {
+ sample = decoded_samples[channel][frames];
+ destination_bus->channelData(channel)[decoded_frames] = sample;
+ }
+ ++decoded_frames;
+ }
+ LOG(INFO) << "decoded_frames : " << decoded_frames
+ << " number_of_frames : " << number_of_frames;
+ if (decoded_frames < number_of_frames)
+ destination_bus->resizeSmaller(decoded_frames);
+}
+
+static void BufferAndCopyPcmDataToBus(int input_fd,
+ blink::WebAudioBus* destination_bus,
+ unsigned number_of_channels,
+ double file_sample_rate) {
+ ssize_t lread = 0;
+ float sample = 0;
+ size_t samples_in_pipe = 0;
+ struct media::WebAudioMediaDataInfoEfl data_info;
+ std::vector<float> decoded_samples[number_of_channels];
+ while ((lread =
+ HANDLE_EINTR(read(input_fd, &data_info, sizeof(data_info)))) > 0) {
+ float pipe_data[data_info.size_ / sizeof(float)];
+
+ lread = HANDLE_EINTR(read(input_fd, pipe_data, sizeof(pipe_data)));
+ samples_in_pipe = lread / sizeof(float);
+
+ for (int i = 0; i < number_of_channels; i++) {
+ if ((decoded_samples[i].size() + samples_in_pipe) >
+ decoded_samples[i].capacity()) {
+ decoded_samples[i].reserve(
+ std::max(samples_in_pipe, 2 * decoded_samples[i].capacity()));
+ }
+ }
+ std::copy(pipe_data, pipe_data + samples_in_pipe,
+ back_inserter(decoded_samples[data_info.channel_mask_ - 1]));
+ }
+ size_t number_of_samples = 0;
+ for (int i = 0; i < number_of_channels; i++) {
+ number_of_samples += decoded_samples[i].size();
+ }
+ size_t number_of_frames = number_of_samples / number_of_channels;
+ size_t decoded_frames = 0;
+ destination_bus->initialize(number_of_channels,
+ number_of_frames,
+ file_sample_rate);
+
+ for (size_t frames = 0; frames < number_of_frames; frames++) {
+ for (size_t channel = 0; channel < number_of_channels; channel++) {
+ sample = decoded_samples[channel][frames];
+ destination_bus->channelData(channel)[decoded_frames] = sample;
+ }
+ ++decoded_frames;
+ }
+ LOG(INFO) << "decoded_frames : " << decoded_frames
+ << " number_of_frames : " << number_of_frames;
+
+ if (decoded_frames < number_of_frames)
+ destination_bus->resizeSmaller(decoded_frames);
+}
+
+// Decode in-memory audio file data.
+bool DecodeAudioFileData(blink::WebAudioBus* destination_bus,
+ const char* data, size_t data_size,
+ scoped_refptr<ThreadSafeSender> sender) {
+ AudioDecoderIO audio_decoder(data, data_size);
+
+ if (!audio_decoder.IsValid()) {
+ LOG(ERROR) << "Invalid audio_decoder";
+ return false;
+ }
+
+ base::SharedMemoryHandle encoded_data_handle;
+ audio_decoder.ShareEncodedDataToProcess(&encoded_data_handle);
+ base::FileDescriptor fd(audio_decoder.GetWriteFd(), true);
+
+ // Start Decoding in browser process which will read from
+ // encoded_data_handle for our shared memory and write the decoded
+ // PCM samples (16-bit integer) to our pipe.
+
+ sender->Send(new EflViewHostMsg_WebAudioDecode(encoded_data_handle,
+ fd, data_size));
+
+ int input_fd = audio_decoder.GetReadFd();
+ struct media::WebAudioMediaCodecInfoEfl info;
+
+ ssize_t nread = HANDLE_EINTR(read(input_fd, &info, sizeof(info)));
+
+ if (nread != sizeof(info)) {
+ LOG(ERROR) << "Read Failed";
+ return false;
+ }
+
+ double file_sample_rate = static_cast<double>(info.sample_rate_);
+
+ // Sanity checks
+ if (!info.channel_count_ ||
+ info.channel_count_ > media::limits::kMaxChannels ||
+ file_sample_rate < media::limits::kMinSampleRate ||
+ file_sample_rate > media::limits::kMaxSampleRate) {
+ return false;
+ }
+
+ if (info.number_of_frames_> 0) {
+ CopyPcmDataToBus(input_fd, destination_bus, info.number_of_frames_,
+ info.channel_count_, file_sample_rate);
+ } else {
+ BufferAndCopyPcmDataToBus(input_fd, destination_bus,
+ info.channel_count_, file_sample_rate);
+ }
+
+ return true;
+}
+
+} // namespace content
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/media/efl/webaudio_decoder_browser_gstreamer.h"
+#include "media/base/efl/webaudio_decoder_browser_gstreamer.h"
#include <gst/app/gstappsink.h>
#include <gst/app/gstappsrc.h>
#include "media/base/efl/webaudio_media_codec_info_efl.h"
#include "third_party/WebKit/public/platform/WebAudioBus.h"
-namespace content {
+namespace media {
#define CHUNK_SIZE 204800 // (4096*50)
#define GST_OBJECT_UNREF(obj) \
uint16_t number_of_channels,
uint32_t sample_rate,
size_t number_of_frames) {
- struct media::WebAudioMediaCodecInfoEfl info = {
+ media::WebAudioMediaCodecInfoEfl info(
static_cast<unsigned long>(number_of_channels),
static_cast<unsigned long>(sample_rate),
- static_cast<unsigned long>(number_of_frames)
- };
+ static_cast<unsigned long>(number_of_frames));
HANDLE_EINTR(write(pcm_output, &info, sizeof(info)));
}
}
// WebAudioDecoderGStreamer class
+// static
+WebAudioDecoder* WebAudioDecoder::GetWebAudioDecoder() {
+ return WebAudioDecoderGStreamer::GetInstance();
+}
// static
WebAudioDecoderGStreamer* WebAudioDecoderGStreamer::GetInstance() {
pcm_output, data_size));
}
-} // namespace content
+} // namespace media
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_MEDIA_EFL_WEBAUDIO_DECODER_BROWSER_GSTREAMER_H_
-#define CONTENT_BROWSER_MEDIA_EFL_WEBAUDIO_DECODER_BROWSER_GSTREAMER_H_
+#ifndef MEDIA_BASE_EFL_WEBAUDIO_DECODER_BROWSER_GSTREAMER_H_
+#define MEDIA_BASE_EFL_WEBAUDIO_DECODER_BROWSER_GSTREAMER_H_
#include "base/basictypes.h"
#include "base/memory/singleton.h"
#include "base/memory/shared_memory.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
+#include "media/base/efl/webaudio_decoder_efl.h"
-namespace content {
+namespace media {
// WebAudioDecoderGStreamer class
-class CONTENT_EXPORT WebAudioDecoderGStreamer {
+class MEDIA_EXPORT WebAudioDecoderGStreamer : public WebAudioDecoder {
public:
static WebAudioDecoderGStreamer* GetInstance();
+ // media::WebAudioDecoder implementation.
void EncodedDataReceived(base::SharedMemoryHandle foreign_memory_handle,
base::FileDescriptor pcm_output,
- uint32_t data_size);
+ uint32_t data_size) override;
private:
friend struct base::DefaultSingletonTraits<WebAudioDecoderGStreamer>;
DISALLOW_COPY_AND_ASSIGN(WebAudioDecoderGStreamer);
};
-} // namespace content
+} // namespace media
-#endif // CONTENT_BROWSER_MEDIA_EFL_WEBAUDIO_DECODER_BROWSER_GSTREAMER_H_
+#endif // MEDIA_BASE_EFL_WEBAUDIO_DECODER_BROWSER_GSTREAMER_H_
--- /dev/null
+// Copyright 2014 Samsung Electronics Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_EFL_WEBAUDIO_DECODER_EFL_H_
+#define MEDIA_BASE_EFL_WEBAUDIO_DECODER_EFL_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/shared_memory.h"
+#include "media/base/media_export.h"
+
+namespace media {
+
+class MEDIA_EXPORT WebAudioDecoder {
+ public:
+ static WebAudioDecoder* GetWebAudioDecoder();
+ virtual void EncodedDataReceived(base::SharedMemoryHandle memory_handle,
+ base::FileDescriptor pcm_output,
+ uint32_t data_size) = 0;
+};
+
+} // namespace media
+#endif // MEDIA_BASE_EFL_WEBAUDIO_DECODER_EFL_H_
// determined by MediaCodec that is needed by the audio decoder to
// create the necessary destination bus.
struct WebAudioMediaCodecInfoEfl {
- unsigned long channel_count;
- unsigned long sample_rate;
- unsigned long number_of_frames;
+ unsigned long channel_count_;
+ unsigned long sample_rate_;
+ unsigned long number_of_frames_;
+ WebAudioMediaCodecInfoEfl(unsigned long channel_count = 0,
+ unsigned long sample_rate = 0,
+ unsigned long number_of_frames = 0)
+ : channel_count_(channel_count),
+ sample_rate_(sample_rate),
+ number_of_frames_(number_of_frames) {}
+};
+
+struct WebAudioMediaDataInfoEfl {
+ int channel_mask_;
+ int size_;
+ WebAudioMediaDataInfoEfl(int channel_mask = 0, int size = 0)
+ : channel_mask_(channel_mask),
+ size_(size) {}
};
} // namespace media
-#endif // MEDIA_BASE_EFL_WEBAUDIO_MEDIA_CODEC_INFO_EFL_H_
\ No newline at end of file
+#endif // MEDIA_BASE_EFL_WEBAUDIO_MEDIA_CODEC_INFO_EFL_H_
--- /dev/null
+// Copyright 2015 Samsung Electronics Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/tizen/webaudio_decoder_browser_capi.h"
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/logging.h"
+#include "media/base/efl/webaudio_media_codec_info_efl.h"
+
+namespace {
+
+const int kChannelCount = 2;
+
+const int kSampleRate = 44100;
+
+struct ErrorList {
+ player_error_e error_code;
+ std::string error_message;
+};
+
+// FIXME: Move to common place
+const struct ErrorList errorlist[] = {
+ {PLAYER_ERROR_OUT_OF_MEMORY, "PLAYER_ERROR_OUT_OF_MEMORY"},
+ {PLAYER_ERROR_INVALID_PARAMETER, "PLAYER_ERROR_INVALID_PARAMETER"},
+ {PLAYER_ERROR_NO_SUCH_FILE, "PLAYER_ERROR_NO_SUCH_FILE"},
+ {PLAYER_ERROR_INVALID_OPERATION, "PLAYER_ERROR_INVALID_OPERATION"},
+ {PLAYER_ERROR_FILE_NO_SPACE_ON_DEVICE,
+ "PLAYER_ERROR_FILE_NO_SPACE_ON_DEVICE"},
+ {PLAYER_ERROR_FEATURE_NOT_SUPPORTED_ON_DEVICE,
+ "PLAYER_ERROR_FEATURE_NOT_SUPPORTED_ON_DEVICE"},
+ {PLAYER_ERROR_SEEK_FAILED, "PLAYER_ERROR_SEEK_FAILED"},
+ {PLAYER_ERROR_INVALID_STATE, "PLAYER_ERROR_INVALID_STATE"},
+ {PLAYER_ERROR_NOT_SUPPORTED_FILE, "PLAYER_ERROR_NOT_SUPPORTED_FILE"},
+ {PLAYER_ERROR_INVALID_URI, "PLAYER_ERROR_INVALID_URI"},
+ {PLAYER_ERROR_SOUND_POLICY, "PLAYER_ERROR_SOUND_POLICY"},
+ {PLAYER_ERROR_CONNECTION_FAILED, "PLAYER_ERROR_CONNECTION_FAILED"},
+ {PLAYER_ERROR_VIDEO_CAPTURE_FAILED, "PLAYER_ERROR_VIDEO_CAPTURE_FAILED"},
+ {PLAYER_ERROR_DRM_EXPIRED, "PLAYER_ERROR_DRM_EXPIRED"},
+ {PLAYER_ERROR_DRM_NO_LICENSE, "PLAYER_ERROR_DRM_NO_LICENSE"},
+ {PLAYER_ERROR_DRM_FUTURE_USE, "PLAYER_ERROR_DRM_FUTURE_USE"},
+ {PLAYER_ERROR_DRM_NOT_PERMITTED, "PLAYER_ERROR_DRM_NOT_PERMITTED"},
+ {PLAYER_ERROR_RESOURCE_LIMIT, "PLAYER_ERROR_RESOURCE_LIMIT"},
+ {PLAYER_ERROR_PERMISSION_DENIED, "PLAYER_ERROR_PERMISSION_DENIED"}};
+
+const int ERROR_MAX = sizeof(errorlist) / sizeof(errorlist[0]);
+
+static void PlayerPreparedCb(void* data) {
+ media::AudioDecoderCapi* player =
+ static_cast<media::AudioDecoderCapi*>(data);
+ if (!player)
+ return;
+ player->OnPlayerPrepared();
+}
+
+static void PlayerDecodedBufferReadyCb(player_audio_raw_data_s* audio_data,
+ void* data) {
+ media::AudioDecoderCapi* player =
+ static_cast<media::AudioDecoderCapi*>(data);
+ if (!player)
+ return;
+ player->OnPlayerDecodedBufferReady(audio_data);
+}
+
+static void PlayerEosCb(void* data) {
+ media::AudioDecoderCapi* player =
+ static_cast<media::AudioDecoderCapi*>(data);
+ if (!player)
+ return;
+ player->OnPlayerEos();
+}
+
+static void PlayerErrorCb(int error_code, void* data) {
+ media::AudioDecoderCapi* player =
+ static_cast<media::AudioDecoderCapi*>(data);
+ if (!player)
+ return;
+ player->OnPlayerError(error_code, "PlayerErrorCb");
+}
+
+} // namespace
+
+namespace media {
+
+struct WAPCMdata{
+ uint8_t* data_;
+ int rate_;
+ int size_;
+ int channel_mask_;
+ WAPCMdata(int rate, int size, int channel_mask)
+ : data_(NULL),
+ rate_(rate),
+ size_(size),
+ channel_mask_(channel_mask) {}
+};
+
+AudioDecoderCapi::AudioDecoderCapi(
+ base::FileDescriptor pcm_output,
+ uint8_t* data,
+ uint32_t data_size)
+ : decoder_thread_("CAPIAudioDecoder"),
+ pcm_output_(pcm_output.fd),
+ player_(NULL),
+ data_size_(data_size),
+ encoded_data_(data),
+ is_new_request_(true),
+ is_running_(true) {
+}
+
+AudioDecoderCapi::~AudioDecoderCapi() {
+ if (player_) {
+ player_unset_error_cb(player_);
+ player_unset_completed_cb(player_);
+ player_unprepare(player_);
+ player_destroy(player_);
+ }
+ player_ = NULL;
+ if (decoder_thread_.IsRunning())
+ decoder_thread_.Stop();
+
+ close(pcm_output_);
+}
+
+void AudioDecoderCapi::InitializePlayer() {
+ int error = player_create(&player_);
+ if (error != PLAYER_ERROR_NONE) {
+ PlayerError(error, "player_create");
+ return;
+ }
+
+ player_set_completed_cb(player_, PlayerEosCb, this);
+ player_set_error_cb(player_, PlayerErrorCb, this);
+ player_set_pcm_extraction_mode(player_, false,
+ PlayerDecodedBufferReadyCb, this);
+
+ player_set_pcm_spec(player_, "F32LE", kSampleRate, kChannelCount);
+
+ error = player_set_memory_buffer(player_, encoded_data_, data_size_);
+ if (error != PLAYER_ERROR_NONE) {
+ PlayerError(error, "player_set_memory_buffer");
+ return;
+ }
+
+ error = player_prepare_async(player_, PlayerPreparedCb, this);
+ if (error != PLAYER_ERROR_NONE) {
+ PlayerError(error, "player_prepare_async");
+ return;
+ }
+}
+
+void AudioDecoderCapi::StartDecodeProcess() {
+ InitializePlayer();
+}
+
+void AudioDecoderCapi::PlayerPrepared() {
+ int error = player_start(player_);
+ if (error != PLAYER_ERROR_NONE)
+ PlayerError(error, "player_start()");
+}
+
+static void SendData(const int pcm_out, WAPCMdata* audio_data) {
+ if (!audio_data)
+ return;
+ uint8_t* data = audio_data->data_;
+ int data_size = audio_data->size_;
+ while (data_size > 0) {
+ int bytes_to_write = (data_size >= PIPE_BUF) ? PIPE_BUF : data_size;
+ media::WebAudioMediaDataInfoEfl data_info(audio_data->channel_mask_,
+ bytes_to_write);
+ HANDLE_EINTR(write(pcm_out, &data_info, sizeof(data_info)));
+ ssize_t bytes_written = HANDLE_EINTR(write(pcm_out, data, bytes_to_write));
+ if (bytes_written == -1) {
+ LOG(ERROR) << "Write Failed\n";
+ break;
+ }
+ data_size -= bytes_written;
+ data += bytes_written;
+ }
+}
+
+void AudioDecoderCapi::PlayerDecodedBufferReady(WAPCMdata* audio_data) {
+ if (audio_data->size_ <= 0) {
+ LOG(ERROR) << "Decoded buffer size is invalid";
+ return;
+ }
+
+ if (is_new_request_) {
+ // TODO: How to handle more than 2 channels
+ media::WebAudioMediaCodecInfoEfl info(
+ static_cast<unsigned long>(kChannelCount),
+ static_cast<unsigned long>(audio_data->rate_),
+ static_cast<unsigned long>((audio_data->size_ / sizeof(float))));
+
+ HANDLE_EINTR(write(pcm_output_, &info, sizeof(info)));
+ is_new_request_ = false;
+ }
+ SendData(pcm_output_, audio_data);
+ delete[] (audio_data->data_);
+ delete(audio_data);
+}
+
+void AudioDecoderCapi::PlayerEos() {
+ is_running_ = false;
+}
+
+void AudioDecoderCapi::PlayerError(int err, char const* from) {
+ for (int index = 0; index < ERROR_MAX; ++index) {
+ if (errorlist[index].error_code == err) {
+ LOG(ERROR) << "Stoping decoding due to error code : " << err
+ << " Error message : " << errorlist[index].error_message
+ << " from " << from;
+ break;
+ }
+ }
+
+ is_running_ = false;
+}
+
+void AudioDecoderCapi::OnPlayerPrepared() {
+ decoder_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&AudioDecoderCapi::PlayerPrepared,
+ base::Unretained(this)));
+}
+
+void AudioDecoderCapi::OnPlayerDecodedBufferReady(
+ player_audio_raw_data_s* audio_data) {
+ DCHECK(!decoder_thread_.IsRunning());
+
+ // The buffer is resued by CAPI in next iteration,
+ // this leaves junk data in it hence making local copy.
+ WAPCMdata* localdata = new WAPCMdata(audio_data->rate,
+ audio_data->size,
+ audio_data->channel_mask);
+ localdata->data_ = new uint8_t[localdata->size_];
+ memcpy(localdata->data_, audio_data->data, localdata->size_);
+
+ decoder_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&AudioDecoderCapi::PlayerDecodedBufferReady,
+ base::Unretained(this), localdata));
+}
+
+void AudioDecoderCapi::OnPlayerEos() {
+ decoder_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&AudioDecoderCapi::PlayerEos,
+ base::Unretained(this)));
+}
+
+void AudioDecoderCapi::OnPlayerError(int error_code, const char* msg) {
+ decoder_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&AudioDecoderCapi::PlayerError,
+ base::Unretained(this), error_code, msg));
+}
+
+void AudioDecoderCapi::OnStartDecodeProcess() {
+ if (!decoder_thread_.IsRunning() && !decoder_thread_.Start()) {
+ LOG(ERROR) << "Decoder thread start failed";
+ return;
+ }
+
+ decoder_thread_.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&AudioDecoderCapi::StartDecodeProcess,
+ base::Unretained(this)));
+
+ // TODO(kodam): Need to refactor this class not to use usleep(10) in here.
+ while (is_running_)
+ usleep(10);
+}
+
+// WebAudioDecoderCapi class
+WebAudioDecoder* WebAudioDecoder::GetWebAudioDecoder(){
+ return WebAudioDecoderCapi::GetInstance();
+}
+
+// static
+WebAudioDecoderCapi* WebAudioDecoderCapi::GetInstance() {
+ return base::Singleton<WebAudioDecoderCapi>::get();
+}
+
+WebAudioDecoderCapi::WebAudioDecoderCapi()
+ : capi_thread_("CapiThread") {
+}
+
+WebAudioDecoderCapi::~WebAudioDecoderCapi() {
+}
+
+void WebAudioDecoderCapi::DecodeUsingCAPI(
+ base::SharedMemoryHandle foreign_memory_handle,
+ base::FileDescriptor pcm_output,
+ uint32_t data_size) {
+ base::SharedMemory shared_memory(foreign_memory_handle, false);
+ if (!shared_memory.Map(data_size)) {
+ LOG(ERROR) << "Failed to map shared memory for size " << data_size;
+ return;
+ }
+
+ // This will execute until decoding is done
+ AudioDecoderCapi capi_Decoder(pcm_output,
+ static_cast<uint8_t*>(shared_memory.memory()),
+ data_size);
+ capi_Decoder.OnStartDecodeProcess();
+}
+
+void WebAudioDecoderCapi::EncodedDataReceived(
+ base::SharedMemoryHandle memory_handle,
+ base::FileDescriptor pcm_output,
+ uint32_t data_size) {
+ if (!capi_thread_.IsRunning() && !capi_thread_.Start()) {
+ LOG(ERROR) << "Starting capi thread failed";
+ return;
+ }
+
+ capi_thread_.message_loop()->PostTask(FROM_HERE,
+ base::Bind(&WebAudioDecoderCapi::DecodeUsingCAPI,
+ base::Unretained(this), memory_handle,
+ pcm_output, data_size));
+}
+
+} // namespace media
--- /dev/null
+// Copyright 2015 Samsung Electronics Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_TIZEN_WEBAUDIO_DECODER_BROWSER_CAPI_H_
+#define MEDIA_BASE_TIZEN_WEBAUDIO_DECODER_BROWSER_CAPI_H_
+
+#include <player.h>
+
+#include "base/basictypes.h"
+#include "base/memory/singleton.h"
+#include "base/memory/shared_memory.h"
+#include "base/threading/thread.h"
+#include "media/base/efl/webaudio_decoder_efl.h"
+#include "media/base/media_export.h"
+
+#if defined(USE_LEGACY_PLAYER_CAPI)
+#include <player_product.h>
+#else
+#include <player_internal.h>
+#endif
+
+namespace media {
+
+struct WAPCMdata;
+
+// WebAudioDecoderCapi class
+class MEDIA_EXPORT WebAudioDecoderCapi : public WebAudioDecoder {
+ public:
+ static WebAudioDecoderCapi* GetInstance();
+ virtual ~WebAudioDecoderCapi();
+
+ // media::WebAudioDecoder implementation.
+ void EncodedDataReceived(base::SharedMemoryHandle memory_handle,
+ base::FileDescriptor pcm_output,
+ uint32_t data_size) override;
+
+ private:
+ friend struct base::DefaultSingletonTraits<WebAudioDecoderCapi>;
+ WebAudioDecoderCapi();
+ void DecodeUsingCAPI(base::SharedMemoryHandle foreign_memory_handle,
+ base::FileDescriptor pcm_output,
+ uint32_t data_size);
+
+ base::Thread capi_thread_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebAudioDecoderCapi);
+};
+
+class AudioDecoderCapi {
+ public:
+ AudioDecoderCapi(base::FileDescriptor pcm_output, uint8_t* data,
+ uint32_t data_size);
+ virtual ~AudioDecoderCapi();
+ void OnPlayerPrepared();
+ void OnPlayerDecodedBufferReady(player_audio_raw_data_s* pcm_data);
+ void OnPlayerEos();
+ void OnPlayerError(int error_code, const char* msg);
+ void OnStartDecodeProcess();
+
+ private:
+ void InitializePlayer();
+ void StartDecodeProcess();
+
+ void PlayerPrepared();
+ void PlayerDecodedBufferReady(WAPCMdata* pcm_data);
+ void PlayerEos();
+ void PlayerError(int error_code, const char* msg);
+
+ private:
+ base::Thread decoder_thread_;
+
+ // CAPI player handle.
+ player_h player_;
+
+ // The audio file information and decoded pcm data are written to
+ // this file descriptor. We take ownership of this descriptor.
+ int pcm_output_;
+
+ // The length of the encoded data.
+ uint32_t data_size_;
+
+ // Encoded audio data.
+ uint8_t* encoded_data_;
+
+ bool is_new_request_;
+ bool is_running_;
+};
+
+} // namespace media
+
+#endif // MEDIA_BASE_TIZEN_WEBAUDIO_DECODER_BROWSER_CAPI_H_
'<(DEPTH)/tizen_src/build/system.gyp:ecore',
'<(DEPTH)/tizen_src/build/system.gyp:gstreamer',
'<(DEPTH)/tizen_src/build/system.gyp:capi-media-camera',
+ '<(DEPTH)/tizen_src/build/system.gyp:mm-player',
],
'conditions': [
['use_wayland==0', {
'external_media_deps': [
'<(DEPTH)/tizen_src/build/system.gyp:capi-media-player',
'<(DEPTH)/tizen_src/build/system.gyp:capi-media-tool',
- '<(DEPTH)/ui/gl/gl.gyp:gl',
],
}],
- ['building_for_tizen_tv==1 and chromium_efl_tizen_version!="3.0"', {
- 'defines': [
- 'USE_LEGACY_PLAYER_CAPI=1',
- ],
- }],
],
},
'base/efl/media_player_util_efl.h',
'base/efl/media_source_player_gstreamer.cc',
'base/efl/media_source_player_gstreamer.h',
+ 'base/efl/webaudio_decoder_efl.h',
+ 'base/efl/webaudio_decoder_browser_gstreamer.cc',
+ 'base/efl/webaudio_decoder_browser_gstreamer.h',
],
'conditions': [
['tizen_multimedia_use_capi_for_me==1', {
'sources': [
'base/tizen/media_player_bridge_capi.cc',
- 'base/tizen/media_player_bridge_capi.h', # ME with CAPI-MEDIA-PLAYER
+ 'base/tizen/media_player_bridge_capi.h', # ME
+ 'base/tizen/webaudio_decoder_browser_capi.cc',
+ 'base/tizen/webaudio_decoder_browser_capi.h',
],
# Exclude the sources that depend on CAPI-MEDIA-PLAYER
'sources!': [
'base/efl/media_player_bridge_gstreamer.cc',
- 'base/efl/media_player_bridge_gstreamer.h', # ME with Gstreamer
+ 'base/efl/media_player_bridge_gstreamer.h', # ME
+ 'base/efl/webaudio_decoder_browser_gstreamer.cc',
+ 'base/efl/webaudio_decoder_browser_gstreamer.h',
+ ],
+ }],
+ ['building_for_tizen_tv==1 and chromium_efl_tizen_version!="3.0"', {
+ 'defines': [
+ 'USE_LEGACY_PLAYER_CAPI=1',
],
}],
#include "common/web_contents_utils.h"
#include "content/common/render_messages_efl.h"
-#include "common/render_messages_ewk.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
+#include "common/render_messages_ewk.h"
#include "eweb_view.h"
#include "net/url_request/url_request_context_getter.h"
#include "ipc_message_start_ewk.h"
#if defined(TIZEN_MULTIMEDIA_SUPPORT)
-#include "content/browser/media/efl/webaudio_decoder_browser_gstreamer.h"
+#include "media/base/efl/webaudio_decoder_efl.h"
#endif
using web_contents_utils::WebContentsFromViewID;
bool RenderMessageFilterEfl::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderMessageFilterEfl, message)
- IPC_MESSAGE_HANDLER(EwkHostMsg_DecideNavigationPolicy,
+ IPC_MESSAGE_HANDLER(EwkHostMsg_DecideNavigationPolicy,
OnDecideNavigationPolicy)
#if defined(TIZEN_MULTIMEDIA_SUPPORT)
- IPC_MESSAGE_HANDLER(EflViewHostMsg_GstWebAudioDecode,
- OnGstWebAudioDecode)
+ IPC_MESSAGE_HANDLER(EflViewHostMsg_WebAudioDecode, OnWebAudioDecode)
#endif
- IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
}
#if defined(TIZEN_MULTIMEDIA_SUPPORT)
-void RenderMessageFilterEfl::OnGstWebAudioDecode(
+void RenderMessageFilterEfl::OnWebAudioDecode(
base::SharedMemoryHandle encoded_data_handle,
base::FileDescriptor pcm_output,
uint32_t data_size) {
- content::WebAudioDecoderGStreamer::GetInstance()->EncodedDataReceived(
+ media::WebAudioDecoder::GetWebAudioDecoder()->EncodedDataReceived(
encoded_data_handle, pcm_output, data_size);
}
#endif
const NodeAttributesMap& node_attributes);
#if defined(TIZEN_MULTIMEDIA_SUPPORT)
- void OnGstWebAudioDecode(base::SharedMemoryHandle encoded_data_handle,
- base::FileDescriptor pcm_output,
- uint32_t data_size);
+ void OnWebAudioDecode(base::SharedMemoryHandle encoded_data_handle,
+ base::FileDescriptor pcm_output,
+ uint32_t data_size);
#endif
int render_process_id_;
BuildRequires: pkgconfig(harfbuzz)
BuildRequires: pkgconfig(libtbm)
BuildRequires: pkgconfig(minizip)
+BuildRequires: pkgconfig(mm-player)
BuildRequires: pkgconfig(nspr)
BuildRequires: pkgconfig(openssl)
BuildRequires: pkgconfig(speex)
BuildRequires: pkgconfig(libxml-2.0)
BuildRequires: pkgconfig(libxslt)
BuildRequires: pkgconfig(minizip)
+BuildRequires: pkgconfig(mm-player)
BuildRequires: pkgconfig(nspr)
BuildRequires: pkgconfig(nss)
BuildRequires: pkgconfig(openssl)
BuildRequires: pkgconfig(harfbuzz)
BuildRequires: pkgconfig(libtbm)
BuildRequires: pkgconfig(minizip)
+BuildRequires: pkgconfig(mm-player)
BuildRequires: pkgconfig(nspr)
BuildRequires: pkgconfig(openssl)
BuildRequires: pkgconfig(speex)