Home | History | Annotate | Download | only in services
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "media/mojo/services/media_type_converters.h"
      6 
      7 #include "base/macros.h"
      8 #include "media/base/audio_decoder_config.h"
      9 #include "media/base/buffering_state.h"
     10 #include "media/base/decoder_buffer.h"
     11 #include "media/base/demuxer_stream.h"
     12 #include "media/mojo/interfaces/demuxer_stream.mojom.h"
     13 #include "mojo/public/cpp/system/data_pipe.h"
     14 
     15 namespace mojo {
     16 
     17 #define ASSERT_ENUM_EQ(media_enum, media_prefix, mojo_prefix, value)     \
     18   COMPILE_ASSERT(media::media_prefix##value ==                           \
     19                      static_cast<media::media_enum>(mojo_prefix##value), \
     20                  value##_enum_value_differs)
     21 
     22 // BufferingState.
     23 ASSERT_ENUM_EQ(BufferingState, BUFFERING_, BUFFERING_STATE_, HAVE_NOTHING);
     24 ASSERT_ENUM_EQ(BufferingState, BUFFERING_, BUFFERING_STATE_, HAVE_ENOUGH);
     25 
     26 // AudioCodec.
     27 COMPILE_ASSERT(media::kUnknownAudioCodec ==
     28                    static_cast<media::AudioCodec>(AUDIO_CODEC_UNKNOWN),
     29                kUnknownAudioCodec_enum_value_differs);
     30 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, AAC);
     31 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, MP3);
     32 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, PCM);
     33 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, Vorbis);
     34 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, FLAC);
     35 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, AMR_NB);
     36 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, PCM_MULAW);
     37 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, GSM_MS);
     38 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, PCM_S16BE);
     39 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, PCM_S24BE);
     40 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, Opus);
     41 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, PCM_ALAW);
     42 COMPILE_ASSERT(media::kAudioCodecMax ==
     43                    static_cast<media::AudioCodec>(AUDIO_CODEC_MAX),
     44                kAudioCodecMax_enum_value_differs);
     45 
     46 // ChannelLayout.
     47 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _NONE);
     48 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _UNSUPPORTED);
     49 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _MONO);
     50 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _STEREO);
     51 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _2_1);
     52 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _SURROUND);
     53 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _4_0);
     54 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _2_2);
     55 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _QUAD);
     56 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _5_0);
     57 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _5_1);
     58 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _5_0_BACK);
     59 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _5_1_BACK);
     60 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _7_0);
     61 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _7_1);
     62 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _7_1_WIDE);
     63 ASSERT_ENUM_EQ(ChannelLayout,
     64                CHANNEL_LAYOUT,
     65                CHANNEL_LAYOUT_k,
     66                _STEREO_DOWNMIX);
     67 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _2POINT1);
     68 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _3_1);
     69 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _4_1);
     70 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _6_0);
     71 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _6_0_FRONT);
     72 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _HEXAGONAL);
     73 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _6_1);
     74 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _6_1_BACK);
     75 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _6_1_FRONT);
     76 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _7_0_FRONT);
     77 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _7_1_WIDE_BACK);
     78 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _OCTAGONAL);
     79 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _DISCRETE);
     80 ASSERT_ENUM_EQ(ChannelLayout,
     81                CHANNEL_LAYOUT,
     82                CHANNEL_LAYOUT_k,
     83                _STEREO_AND_KEYBOARD_MIC);
     84 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _MAX);
     85 
     86 // SampleFormat.
     87 COMPILE_ASSERT(media::kUnknownSampleFormat ==
     88                    static_cast<media::SampleFormat>(SAMPLE_FORMAT_UNKNOWN),
     89                kUnknownSampleFormat_enum_value_differs);
     90 ASSERT_ENUM_EQ(SampleFormat, kSampleFormat, SAMPLE_FORMAT_, U8);
     91 ASSERT_ENUM_EQ(SampleFormat, kSampleFormat, SAMPLE_FORMAT_, S16);
     92 ASSERT_ENUM_EQ(SampleFormat, kSampleFormat, SAMPLE_FORMAT_, S32);
     93 ASSERT_ENUM_EQ(SampleFormat, kSampleFormat, SAMPLE_FORMAT_, F32);
     94 ASSERT_ENUM_EQ(SampleFormat, kSampleFormat, SAMPLE_FORMAT_, PlanarS16);
     95 ASSERT_ENUM_EQ(SampleFormat, kSampleFormat, SAMPLE_FORMAT_, PlanarF32);
     96 ASSERT_ENUM_EQ(SampleFormat, kSampleFormat, SAMPLE_FORMAT_, Max);
     97 
     98 // DemuxerStream Type.
     99 COMPILE_ASSERT(media::DemuxerStream::UNKNOWN ==
    100                    static_cast<media::DemuxerStream::Type>(
    101                        mojo::DemuxerStream::TYPE_UNKNOWN),
    102                DemuxerStream_Type_enum_value_differs);
    103 COMPILE_ASSERT(media::DemuxerStream::AUDIO ==
    104                    static_cast<media::DemuxerStream::Type>(
    105                        mojo::DemuxerStream::TYPE_AUDIO),
    106                DemuxerStream_Type_enum_value_differs);
    107 // Update this if new media::DemuxerStream::Type values are introduced.
    108 COMPILE_ASSERT(media::DemuxerStream::NUM_TYPES ==
    109                    static_cast<media::DemuxerStream::Type>(
    110                        mojo::DemuxerStream::TYPE_LAST_TYPE + 3),
    111                DemuxerStream_Type_enum_value_differs);
    112 
    113 // DemuxerStream Status.
    114 COMPILE_ASSERT(media::DemuxerStream::kOk ==
    115                    static_cast<media::DemuxerStream::Status>(
    116                        mojo::DemuxerStream::STATUS_OK),
    117                DemuxerStream_Status_enum_value_differs);
    118 COMPILE_ASSERT(media::DemuxerStream::kAborted ==
    119                    static_cast<media::DemuxerStream::Status>(
    120                        mojo::DemuxerStream::STATUS_ABORTED),
    121                DemuxerStream_Status_enum_value_differs);
    122 COMPILE_ASSERT(media::DemuxerStream::kConfigChanged ==
    123                    static_cast<media::DemuxerStream::Status>(
    124                        mojo::DemuxerStream::STATUS_CONFIG_CHANGED),
    125                DemuxerStream_Status_enum_value_differs);
    126 
    127 // static
    128 MediaDecoderBufferPtr TypeConverter<MediaDecoderBufferPtr,
    129     scoped_refptr<media::DecoderBuffer> >::Convert(
    130         const scoped_refptr<media::DecoderBuffer>& input) {
    131   MediaDecoderBufferPtr mojo_buffer(MediaDecoderBuffer::New());
    132   mojo_buffer->timestamp_usec = input->timestamp().InMicroseconds();
    133   mojo_buffer->duration_usec = input->duration().InMicroseconds();
    134   mojo_buffer->data_size = input->data_size();
    135   mojo_buffer->side_data_size = input->side_data_size();
    136   mojo_buffer->front_discard_usec =
    137       input->discard_padding().first.InMicroseconds();
    138   mojo_buffer->back_discard_usec =
    139       input->discard_padding().second.InMicroseconds();
    140   mojo_buffer->splice_timestamp_usec =
    141       input->splice_timestamp().InMicroseconds();
    142 
    143   // TODO(tim): Assuming this is small so allowing extra copies.
    144   std::vector<uint8> side_data(input->side_data(),
    145                                input->side_data() + input->side_data_size());
    146   mojo_buffer->side_data.Swap(&side_data);
    147 
    148   MojoCreateDataPipeOptions options;
    149   options.struct_size = sizeof(MojoCreateDataPipeOptions);
    150   options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
    151   options.element_num_bytes = 1;
    152   options.capacity_num_bytes = input->data_size();
    153   DataPipe data_pipe(options);
    154   mojo_buffer->data = data_pipe.consumer_handle.Pass();
    155 
    156   uint32_t num_bytes = input->data_size();
    157   // TODO(tim): ALL_OR_NONE isn't really appropriate. Check success?
    158   // If fails, we'd still return the buffer, but we'd need to HandleWatch
    159   // to fill the pipe at a later time, which means the de-marshalling code
    160   // needs to wait for a readable pipe (which it currently doesn't).
    161   WriteDataRaw(data_pipe.producer_handle.get(),
    162                input->data(),
    163                &num_bytes,
    164                MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
    165   return mojo_buffer.Pass();
    166 }
    167 
    168 // static
    169 scoped_refptr<media::DecoderBuffer>  TypeConverter<
    170     scoped_refptr<media::DecoderBuffer>, MediaDecoderBufferPtr>::Convert(
    171         const MediaDecoderBufferPtr& input) {
    172   uint32_t num_bytes  = 0;
    173   // TODO(tim): We're assuming that because we always write to the pipe above
    174   // before sending the MediaDecoderBuffer that the pipe is readable when
    175   // we get here.
    176   ReadDataRaw(input->data.get(), NULL, &num_bytes, MOJO_READ_DATA_FLAG_QUERY);
    177   CHECK_EQ(num_bytes, input->data_size) << "Pipe error converting buffer";
    178 
    179   scoped_ptr<uint8[]> data(new uint8[num_bytes]);  // Uninitialized.
    180   ReadDataRaw(input->data.get(), data.get(), &num_bytes,
    181               MOJO_READ_DATA_FLAG_ALL_OR_NONE);
    182   CHECK_EQ(num_bytes, input->data_size) << "Pipe error converting buffer";
    183 
    184   // TODO(tim): We can't create a media::DecoderBuffer that has side_data
    185   // without copying data because it wants to ensure alignment. Could we
    186   // read directly into a pre-padded DecoderBuffer?
    187   scoped_refptr<media::DecoderBuffer> buffer;
    188   if (input->side_data_size) {
    189     buffer = media::DecoderBuffer::CopyFrom(data.get(),
    190                                             num_bytes,
    191                                             &input->side_data.front(),
    192                                             input->side_data_size);
    193   } else {
    194     buffer = media::DecoderBuffer::CopyFrom(data.get(), num_bytes);
    195   }
    196 
    197   buffer->set_timestamp(
    198       base::TimeDelta::FromMicroseconds(input->timestamp_usec));
    199   buffer->set_duration(
    200       base::TimeDelta::FromMicroseconds(input->duration_usec));
    201   media::DecoderBuffer::DiscardPadding discard_padding(
    202       base::TimeDelta::FromMicroseconds(input->front_discard_usec),
    203       base::TimeDelta::FromMicroseconds(input->back_discard_usec));
    204   buffer->set_discard_padding(discard_padding);
    205   buffer->set_splice_timestamp(
    206       base::TimeDelta::FromMicroseconds(input->splice_timestamp_usec));
    207   return buffer;
    208 }
    209 
    210 // static
    211 AudioDecoderConfigPtr
    212 TypeConverter<AudioDecoderConfigPtr, media::AudioDecoderConfig>::Convert(
    213     const media::AudioDecoderConfig& input) {
    214   mojo::AudioDecoderConfigPtr config(mojo::AudioDecoderConfig::New());
    215   config->codec = static_cast<mojo::AudioCodec>(input.codec());
    216   config->sample_format =
    217       static_cast<mojo::SampleFormat>(input.sample_format());
    218   config->channel_layout =
    219       static_cast<mojo::ChannelLayout>(input.channel_layout());
    220   config->samples_per_second = input.samples_per_second();
    221   if (input.extra_data()) {
    222     std::vector<uint8> data(input.extra_data(),
    223                             input.extra_data() + input.extra_data_size());
    224     config->extra_data.Swap(&data);
    225   }
    226   config->seek_preroll_usec = input.seek_preroll().InMicroseconds();
    227   config->codec_delay = input.codec_delay();
    228   return config.Pass();
    229 }
    230 
    231 // static
    232 media::AudioDecoderConfig
    233 TypeConverter<media::AudioDecoderConfig, AudioDecoderConfigPtr>::Convert(
    234     const AudioDecoderConfigPtr& input) {
    235   media::AudioDecoderConfig config;
    236   config.Initialize(static_cast<media::AudioCodec>(input->codec),
    237                     static_cast<media::SampleFormat>(input->sample_format),
    238                     static_cast<media::ChannelLayout>(input->channel_layout),
    239                     input->samples_per_second,
    240                     &input->extra_data.front(),
    241                     input->extra_data.size(),
    242                     false,
    243                     false,
    244                     base::TimeDelta::FromMicroseconds(input->seek_preroll_usec),
    245                     input->codec_delay);
    246   return config;
    247 }
    248 
    249 }  // namespace mojo
    250