[MM] Webaudio with CAPI port.
authorpuru <puru.dharma@samsung.com>
Tue, 3 Nov 2015 08:50:04 +0000 (14:20 +0530)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Tue, 10 Jul 2018 07:55:23 +0000 (07:55 +0000)
This patch implements:
1. Webaudio using CAPI player.
2. Decoded output data handling from CAPI interface.
3. Factory interface for webaudio instance creation.

Original M42 patch: http://165.213.202.130/gerrit/#/c/83775/

Bug: http://168.219.209.56/jira/browse/TSAM-56

Reviewed by: sns.park

Change-Id: I413f1f53c7f066620182ce1075f807e06f354ddd
Signed-off-by: puru <puru.dharma@samsung.com>
Signed-off-by: SeungSeop Park <sns.park@samsung.com>
19 files changed:
tizen_src/build/system.gyp
tizen_src/chromium_impl/content/common/render_messages_efl.h
tizen_src/chromium_impl/content/content_browser_efl.gypi
tizen_src/chromium_impl/content/content_renderer_efl.gypi
tizen_src/chromium_impl/content/renderer/media/efl/audio_decoder_efl.h [moved from tizen_src/chromium_impl/content/renderer/media/efl/audio_decoder_gstreamer.h with 55% similarity]
tizen_src/chromium_impl/content/renderer/media/efl/audio_decoder_gstreamer.cc
tizen_src/chromium_impl/content/renderer/media/tizen/audio_decoder_capi.cc [new file with mode: 0644]
tizen_src/chromium_impl/media/base/efl/webaudio_decoder_browser_gstreamer.cc [moved from tizen_src/chromium_impl/content/browser/media/efl/webaudio_decoder_browser_gstreamer.cc with 97% similarity]
tizen_src/chromium_impl/media/base/efl/webaudio_decoder_browser_gstreamer.h [moved from tizen_src/chromium_impl/content/browser/media/efl/webaudio_decoder_browser_gstreamer.h with 68% similarity]
tizen_src/chromium_impl/media/base/efl/webaudio_decoder_efl.h [new file with mode: 0644]
tizen_src/chromium_impl/media/base/efl/webaudio_media_codec_info_efl.h
tizen_src/chromium_impl/media/base/tizen/webaudio_decoder_browser_capi.cc [new file with mode: 0644]
tizen_src/chromium_impl/media/base/tizen/webaudio_decoder_browser_capi.h [new file with mode: 0644]
tizen_src/chromium_impl/media/media_efl.gypi
tizen_src/ewk/efl_integration/browser/render_message_filter_efl.cc
tizen_src/ewk/efl_integration/browser/render_message_filter_efl.h
tizen_src/packaging/chromium-efl-libs.spec
tizen_src/packaging/chromium-efl.spec
tizen_src/packaging/crosswalk-bin.spec

index f432686..8d1d19e 100644 (file)
       ],
     }, # 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': [
index bb91fe8..5a4ae3b 100644 (file)
@@ -26,8 +26,8 @@
 #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*/)
index 02247a6..7105685 100644 (file)
@@ -67,8 +67,6 @@
       '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',
index 8c340fc..81c624c 100644 (file)
@@ -19,8 +19,8 @@
         [ '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
   ],
 }
@@ -2,9 +2,9 @@
 // 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_
index 9163fc4..1e4cd15 100644 (file)
@@ -2,7 +2,7 @@
 // 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"
@@ -18,8 +18,8 @@
 #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);
@@ -208,7 +208,8 @@ bool DecodeAudioFileData(blink::WebAudioBus* destination_bus,
   // 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;
@@ -220,28 +221,26 @@ bool DecodeAudioFileData(blink::WebAudioBus* destination_bus,
     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);
   }
 
diff --git a/tizen_src/chromium_impl/content/renderer/media/tizen/audio_decoder_capi.cc b/tizen_src/chromium_impl/content/renderer/media/tizen/audio_decoder_capi.cc
new file mode 100644 (file)
index 0000000..5cb60a6
--- /dev/null
@@ -0,0 +1,257 @@
+// 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
@@ -2,7 +2,7 @@
 // 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>
@@ -17,7 +17,7 @@
 #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) \
@@ -90,11 +90,10 @@ void GSTDecoder::InitializeGstDestination(int pcm_output,
                                           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)));
 }
@@ -370,6 +369,10 @@ GstBusSyncReply GSTDecoder::OnBusMessage(GstBus* bus,
 }
 
 // WebAudioDecoderGStreamer class
+// static
+WebAudioDecoder* WebAudioDecoder::GetWebAudioDecoder() {
+  return WebAudioDecoderGStreamer::GetInstance();
+}
 
 // static
 WebAudioDecoderGStreamer* WebAudioDecoderGStreamer::GetInstance() {
@@ -425,4 +428,4 @@ void WebAudioDecoderGStreamer::EncodedDataReceived(
       pcm_output, data_size));
 }
 
-}  // namespace content
+}  // namespace media
@@ -2,25 +2,27 @@
 // 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>;
@@ -35,6 +37,6 @@ class CONTENT_EXPORT 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_
diff --git a/tizen_src/chromium_impl/media/base/efl/webaudio_decoder_efl.h b/tizen_src/chromium_impl/media/base/efl/webaudio_decoder_efl.h
new file mode 100644 (file)
index 0000000..9e365fa
--- /dev/null
@@ -0,0 +1,25 @@
+// 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_
index 170ea4f..734f820 100644 (file)
@@ -11,10 +11,24 @@ namespace media {
 // 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_
diff --git a/tizen_src/chromium_impl/media/base/tizen/webaudio_decoder_browser_capi.cc b/tizen_src/chromium_impl/media/base/tizen/webaudio_decoder_browser_capi.cc
new file mode 100644 (file)
index 0000000..8fc8f3b
--- /dev/null
@@ -0,0 +1,324 @@
+// 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
diff --git a/tizen_src/chromium_impl/media/base/tizen/webaudio_decoder_browser_capi.h b/tizen_src/chromium_impl/media/base/tizen/webaudio_decoder_browser_capi.h
new file mode 100644 (file)
index 0000000..fd770ec
--- /dev/null
@@ -0,0 +1,92 @@
+// 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_
index f3c34d1..defb907 100644 (file)
@@ -32,6 +32,7 @@
           '<(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',
-            ],
-         }],
         ],
       },
 
@@ -92,6 +87,9 @@
                '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',
                 ],
               }],
 
index aeb6efd..a929258 100644 (file)
@@ -6,16 +6,16 @@
 
 #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;
@@ -48,13 +48,12 @@ void RenderMessageFilterEfl::OverrideThreadForMessage(
 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;
 }
@@ -71,11 +70,11 @@ void RenderMessageFilterEfl::OnDecideNavigationPolicy(
 }
 
 #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
index 4d81036..6f14907 100644 (file)
@@ -42,9 +42,9 @@ class RenderMessageFilterEfl : public content::BrowserMessageFilter {
       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_;
index e853b08..4f98dcb 100644 (file)
@@ -80,6 +80,7 @@ BuildRequires:  pkgconfig(gstreamer-app-1.0)
 BuildRequires:  pkgconfig(harfbuzz)
 BuildRequires:  pkgconfig(libtbm)
 BuildRequires:  pkgconfig(minizip)
+BuildRequires:  pkgconfig(mm-player)
 BuildRequires:  pkgconfig(nspr)
 BuildRequires:  pkgconfig(openssl)
 BuildRequires:  pkgconfig(speex)
index 5a3896a..88672ef 100644 (file)
@@ -95,6 +95,7 @@ BuildRequires: pkgconfig(libusb-1.0)
 BuildRequires: pkgconfig(libxml-2.0)
 BuildRequires: pkgconfig(libxslt)
 BuildRequires: pkgconfig(minizip)
+BuildRequires: pkgconfig(mm-player)
 BuildRequires: pkgconfig(nspr)
 BuildRequires: pkgconfig(nss)
 BuildRequires: pkgconfig(openssl)
index 636b523..8a8c744 100644 (file)
@@ -96,6 +96,7 @@ BuildRequires:  pkgconfig(gstreamer-app-1.0)
 BuildRequires:  pkgconfig(harfbuzz)
 BuildRequires:  pkgconfig(libtbm)
 BuildRequires:  pkgconfig(minizip)
+BuildRequires:  pkgconfig(mm-player)
 BuildRequires:  pkgconfig(nspr)
 BuildRequires:  pkgconfig(openssl)
 BuildRequires:  pkgconfig(speex)