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.
5 #include "media/mojo/services/media_type_converters.h"
7 #include "media/base/audio_decoder_config.h"
8 #include "media/base/buffering_state.h"
9 #include "media/base/decoder_buffer.h"
10 #include "media/base/demuxer_stream.h"
11 #include "media/base/video_decoder_config.h"
12 #include "media/mojo/interfaces/demuxer_stream.mojom.h"
13 #include "mojo/converters/geometry/geometry_type_converters.h"
14 #include "mojo/public/cpp/system/data_pipe.h"
18 #define ASSERT_ENUM_EQ(media_enum, media_prefix, mojo_prefix, value) \
19 static_assert(media::media_prefix##value == \
20 static_cast<media::media_enum>(mojo_prefix##value), \
21 "Mismatched enum: " #media_prefix #value \
22 " != " #mojo_prefix #value)
24 #define ASSERT_ENUM_EQ_RAW(media_enum, media_enum_value, mojo_enum_value) \
25 static_assert(media::media_enum_value == \
26 static_cast<media::media_enum>(mojo_enum_value), \
27 "Mismatched enum: " #media_enum_value " != " #mojo_enum_value)
30 ASSERT_ENUM_EQ(BufferingState, BUFFERING_, BUFFERING_STATE_, HAVE_NOTHING);
31 ASSERT_ENUM_EQ(BufferingState, BUFFERING_, BUFFERING_STATE_, HAVE_ENOUGH);
34 ASSERT_ENUM_EQ_RAW(AudioCodec, kUnknownAudioCodec, AUDIO_CODEC_UNKNOWN);
35 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, AAC);
36 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, MP3);
37 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, PCM);
38 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, Vorbis);
39 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, FLAC);
40 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, AMR_NB);
41 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, PCM_MULAW);
42 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, GSM_MS);
43 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, PCM_S16BE);
44 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, PCM_S24BE);
45 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, Opus);
46 ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, PCM_ALAW);
47 ASSERT_ENUM_EQ_RAW(AudioCodec, kAudioCodecMax, AUDIO_CODEC_MAX);
50 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _NONE);
51 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _UNSUPPORTED);
52 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _MONO);
53 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _STEREO);
54 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _2_1);
55 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _SURROUND);
56 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _4_0);
57 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _2_2);
58 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _QUAD);
59 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _5_0);
60 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _5_1);
61 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _5_0_BACK);
62 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _5_1_BACK);
63 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _7_0);
64 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _7_1);
65 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _7_1_WIDE);
66 ASSERT_ENUM_EQ(ChannelLayout,
70 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _2POINT1);
71 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _3_1);
72 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _4_1);
73 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _6_0);
74 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _6_0_FRONT);
75 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _HEXAGONAL);
76 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _6_1);
77 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _6_1_BACK);
78 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _6_1_FRONT);
79 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _7_0_FRONT);
80 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _7_1_WIDE_BACK);
81 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _OCTAGONAL);
82 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _DISCRETE);
83 ASSERT_ENUM_EQ(ChannelLayout,
86 _STEREO_AND_KEYBOARD_MIC);
87 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _4_1_QUAD_SIDE);
88 ASSERT_ENUM_EQ(ChannelLayout, CHANNEL_LAYOUT, CHANNEL_LAYOUT_k, _MAX);
91 ASSERT_ENUM_EQ_RAW(SampleFormat, kUnknownSampleFormat, SAMPLE_FORMAT_UNKNOWN);
92 ASSERT_ENUM_EQ(SampleFormat, kSampleFormat, SAMPLE_FORMAT_, U8);
93 ASSERT_ENUM_EQ(SampleFormat, kSampleFormat, SAMPLE_FORMAT_, S16);
94 ASSERT_ENUM_EQ(SampleFormat, kSampleFormat, SAMPLE_FORMAT_, S32);
95 ASSERT_ENUM_EQ(SampleFormat, kSampleFormat, SAMPLE_FORMAT_, F32);
96 ASSERT_ENUM_EQ(SampleFormat, kSampleFormat, SAMPLE_FORMAT_, PlanarS16);
97 ASSERT_ENUM_EQ(SampleFormat, kSampleFormat, SAMPLE_FORMAT_, PlanarF32);
98 ASSERT_ENUM_EQ(SampleFormat, kSampleFormat, SAMPLE_FORMAT_, Max);
100 // DemuxerStream Type. Note: Mojo DemuxerStream's don't have the TEXT type.
101 ASSERT_ENUM_EQ_RAW(DemuxerStream::Type,
102 DemuxerStream::UNKNOWN,
103 DemuxerStream::TYPE_UNKNOWN);
104 ASSERT_ENUM_EQ_RAW(DemuxerStream::Type,
105 DemuxerStream::AUDIO,
106 DemuxerStream::TYPE_AUDIO);
107 ASSERT_ENUM_EQ_RAW(DemuxerStream::Type,
108 DemuxerStream::VIDEO,
109 DemuxerStream::TYPE_VIDEO);
110 ASSERT_ENUM_EQ_RAW(DemuxerStream::Type,
111 DemuxerStream::NUM_TYPES,
112 DemuxerStream::TYPE_LAST_TYPE + 2);
114 // DemuxerStream Status.
115 ASSERT_ENUM_EQ_RAW(DemuxerStream::Status,
117 DemuxerStream::STATUS_OK);
118 ASSERT_ENUM_EQ_RAW(DemuxerStream::Status,
119 DemuxerStream::kAborted,
120 DemuxerStream::STATUS_ABORTED);
121 ASSERT_ENUM_EQ_RAW(DemuxerStream::Status,
122 DemuxerStream::kConfigChanged,
123 DemuxerStream::STATUS_CONFIG_CHANGED);
126 ASSERT_ENUM_EQ_RAW(VideoFrame::Format,
128 VIDEO_FORMAT_UNKNOWN);
129 ASSERT_ENUM_EQ_RAW(VideoFrame::Format, VideoFrame::YV12, VIDEO_FORMAT_YV12);
130 ASSERT_ENUM_EQ_RAW(VideoFrame::Format, VideoFrame::YV16, VIDEO_FORMAT_YV16);
131 ASSERT_ENUM_EQ_RAW(VideoFrame::Format, VideoFrame::I420, VIDEO_FORMAT_I420);
132 ASSERT_ENUM_EQ_RAW(VideoFrame::Format, VideoFrame::YV12A, VIDEO_FORMAT_YV12A);
133 #if defined(VIDEO_HOLE)
134 ASSERT_ENUM_EQ_RAW(VideoFrame::Format, VideoFrame::HOLE, VIDEO_FORMAT_HOLE);
136 ASSERT_ENUM_EQ_RAW(VideoFrame::Format,
137 VideoFrame::NATIVE_TEXTURE,
138 VIDEO_FORMAT_NATIVE_TEXTURE);
139 ASSERT_ENUM_EQ_RAW(VideoFrame::Format, VideoFrame::YV12J, VIDEO_FORMAT_YV12J);
140 ASSERT_ENUM_EQ_RAW(VideoFrame::Format, VideoFrame::NV12, VIDEO_FORMAT_NV12);
141 ASSERT_ENUM_EQ_RAW(VideoFrame::Format, VideoFrame::YV24, VIDEO_FORMAT_YV24);
142 ASSERT_ENUM_EQ_RAW(VideoFrame::Format,
143 VideoFrame::FORMAT_MAX,
144 VIDEO_FORMAT_FORMAT_MAX);
147 ASSERT_ENUM_EQ_RAW(VideoCodec, kUnknownVideoCodec, VIDEO_CODEC_UNKNOWN);
148 ASSERT_ENUM_EQ(VideoCodec, kCodec, VIDEO_CODEC_, H264);
149 ASSERT_ENUM_EQ(VideoCodec, kCodec, VIDEO_CODEC_, VC1);
150 ASSERT_ENUM_EQ(VideoCodec, kCodec, VIDEO_CODEC_, MPEG2);
151 ASSERT_ENUM_EQ(VideoCodec, kCodec, VIDEO_CODEC_, MPEG4);
152 ASSERT_ENUM_EQ(VideoCodec, kCodec, VIDEO_CODEC_, Theora);
153 ASSERT_ENUM_EQ(VideoCodec, kCodec, VIDEO_CODEC_, VP8);
154 ASSERT_ENUM_EQ(VideoCodec, kCodec, VIDEO_CODEC_, VP9);
155 ASSERT_ENUM_EQ_RAW(VideoCodec, kVideoCodecMax, VIDEO_CODEC_Max);
158 ASSERT_ENUM_EQ(VideoCodecProfile,
160 VIDEO_CODEC_PROFILE_,
161 VIDEO_CODEC_PROFILE_UNKNOWN);
162 ASSERT_ENUM_EQ(VideoCodecProfile,
164 VIDEO_CODEC_PROFILE_,
165 VIDEO_CODEC_PROFILE_MIN);
166 ASSERT_ENUM_EQ(VideoCodecProfile, , VIDEO_CODEC_PROFILE_, H264PROFILE_MIN);
167 ASSERT_ENUM_EQ(VideoCodecProfile, , VIDEO_CODEC_PROFILE_, H264PROFILE_BASELINE);
168 ASSERT_ENUM_EQ(VideoCodecProfile, , VIDEO_CODEC_PROFILE_, H264PROFILE_MAIN);
169 ASSERT_ENUM_EQ(VideoCodecProfile, , VIDEO_CODEC_PROFILE_, H264PROFILE_EXTENDED);
170 ASSERT_ENUM_EQ(VideoCodecProfile, , VIDEO_CODEC_PROFILE_, H264PROFILE_HIGH);
171 ASSERT_ENUM_EQ(VideoCodecProfile,
173 VIDEO_CODEC_PROFILE_,
174 H264PROFILE_HIGH10PROFILE);
175 ASSERT_ENUM_EQ(VideoCodecProfile,
177 VIDEO_CODEC_PROFILE_,
178 H264PROFILE_HIGH422PROFILE);
179 ASSERT_ENUM_EQ(VideoCodecProfile,
181 VIDEO_CODEC_PROFILE_,
182 H264PROFILE_HIGH444PREDICTIVEPROFILE);
183 ASSERT_ENUM_EQ(VideoCodecProfile,
185 VIDEO_CODEC_PROFILE_,
186 H264PROFILE_SCALABLEBASELINE);
187 ASSERT_ENUM_EQ(VideoCodecProfile,
189 VIDEO_CODEC_PROFILE_,
190 H264PROFILE_SCALABLEHIGH);
191 ASSERT_ENUM_EQ(VideoCodecProfile,
193 VIDEO_CODEC_PROFILE_,
194 H264PROFILE_STEREOHIGH);
195 ASSERT_ENUM_EQ(VideoCodecProfile,
197 VIDEO_CODEC_PROFILE_,
198 H264PROFILE_MULTIVIEWHIGH);
199 ASSERT_ENUM_EQ(VideoCodecProfile, , VIDEO_CODEC_PROFILE_, H264PROFILE_MAX);
200 ASSERT_ENUM_EQ(VideoCodecProfile, , VIDEO_CODEC_PROFILE_, VP8PROFILE_MIN);
201 ASSERT_ENUM_EQ(VideoCodecProfile, , VIDEO_CODEC_PROFILE_, VP8PROFILE_ANY);
202 ASSERT_ENUM_EQ(VideoCodecProfile, , VIDEO_CODEC_PROFILE_, VP8PROFILE_MAX);
203 ASSERT_ENUM_EQ(VideoCodecProfile, , VIDEO_CODEC_PROFILE_, VP9PROFILE_MIN);
204 ASSERT_ENUM_EQ(VideoCodecProfile, , VIDEO_CODEC_PROFILE_, VP9PROFILE_ANY);
205 ASSERT_ENUM_EQ(VideoCodecProfile, , VIDEO_CODEC_PROFILE_, VP9PROFILE_MAX);
206 ASSERT_ENUM_EQ(VideoCodecProfile,
208 VIDEO_CODEC_PROFILE_,
209 VIDEO_CODEC_PROFILE_MAX);
212 MediaDecoderBufferPtr TypeConverter<MediaDecoderBufferPtr,
213 scoped_refptr<media::DecoderBuffer> >::Convert(
214 const scoped_refptr<media::DecoderBuffer>& input) {
215 MediaDecoderBufferPtr mojo_buffer(MediaDecoderBuffer::New());
216 DCHECK(!mojo_buffer->data.is_valid());
218 if (input->end_of_stream())
219 return mojo_buffer.Pass();
221 mojo_buffer->timestamp_usec = input->timestamp().InMicroseconds();
222 mojo_buffer->duration_usec = input->duration().InMicroseconds();
223 mojo_buffer->data_size = input->data_size();
224 mojo_buffer->side_data_size = input->side_data_size();
225 mojo_buffer->front_discard_usec =
226 input->discard_padding().first.InMicroseconds();
227 mojo_buffer->back_discard_usec =
228 input->discard_padding().second.InMicroseconds();
229 mojo_buffer->splice_timestamp_usec =
230 input->splice_timestamp().InMicroseconds();
232 // TODO(tim): Assuming this is small so allowing extra copies.
233 std::vector<uint8> side_data(input->side_data(),
234 input->side_data() + input->side_data_size());
235 mojo_buffer->side_data.Swap(&side_data);
237 MojoCreateDataPipeOptions options;
238 options.struct_size = sizeof(MojoCreateDataPipeOptions);
239 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
240 options.element_num_bytes = 1;
241 options.capacity_num_bytes = input->data_size();
242 DataPipe data_pipe(options);
243 mojo_buffer->data = data_pipe.consumer_handle.Pass();
245 uint32_t num_bytes = input->data_size();
246 // TODO(tim): ALL_OR_NONE isn't really appropriate. Check success?
247 // If fails, we'd still return the buffer, but we'd need to HandleWatch
248 // to fill the pipe at a later time, which means the de-marshalling code
249 // needs to wait for a readable pipe (which it currently doesn't).
250 WriteDataRaw(data_pipe.producer_handle.get(),
253 MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
254 return mojo_buffer.Pass();
258 scoped_refptr<media::DecoderBuffer> TypeConverter<
259 scoped_refptr<media::DecoderBuffer>, MediaDecoderBufferPtr>::Convert(
260 const MediaDecoderBufferPtr& input) {
261 if (!input->data.is_valid())
262 return media::DecoderBuffer::CreateEOSBuffer();
264 uint32_t num_bytes = 0;
265 // TODO(tim): We're assuming that because we always write to the pipe above
266 // before sending the MediaDecoderBuffer that the pipe is readable when
268 ReadDataRaw(input->data.get(), NULL, &num_bytes, MOJO_READ_DATA_FLAG_QUERY);
269 CHECK_EQ(num_bytes, input->data_size) << "Pipe error converting buffer";
271 scoped_ptr<uint8[]> data(new uint8[num_bytes]); // Uninitialized.
272 ReadDataRaw(input->data.get(), data.get(), &num_bytes,
273 MOJO_READ_DATA_FLAG_ALL_OR_NONE);
274 CHECK_EQ(num_bytes, input->data_size) << "Pipe error converting buffer";
276 // TODO(tim): We can't create a media::DecoderBuffer that has side_data
277 // without copying data because it wants to ensure alignment. Could we
278 // read directly into a pre-padded DecoderBuffer?
279 scoped_refptr<media::DecoderBuffer> buffer;
280 if (input->side_data_size) {
281 buffer = media::DecoderBuffer::CopyFrom(data.get(),
283 &input->side_data.front(),
284 input->side_data_size);
286 buffer = media::DecoderBuffer::CopyFrom(data.get(), num_bytes);
289 buffer->set_timestamp(
290 base::TimeDelta::FromMicroseconds(input->timestamp_usec));
291 buffer->set_duration(
292 base::TimeDelta::FromMicroseconds(input->duration_usec));
293 media::DecoderBuffer::DiscardPadding discard_padding(
294 base::TimeDelta::FromMicroseconds(input->front_discard_usec),
295 base::TimeDelta::FromMicroseconds(input->back_discard_usec));
296 buffer->set_discard_padding(discard_padding);
297 buffer->set_splice_timestamp(
298 base::TimeDelta::FromMicroseconds(input->splice_timestamp_usec));
303 AudioDecoderConfigPtr
304 TypeConverter<AudioDecoderConfigPtr, media::AudioDecoderConfig>::Convert(
305 const media::AudioDecoderConfig& input) {
306 AudioDecoderConfigPtr config(AudioDecoderConfig::New());
307 config->codec = static_cast<AudioCodec>(input.codec());
308 config->sample_format =
309 static_cast<SampleFormat>(input.sample_format());
310 config->channel_layout =
311 static_cast<ChannelLayout>(input.channel_layout());
312 config->samples_per_second = input.samples_per_second();
313 if (input.extra_data()) {
314 std::vector<uint8> data(input.extra_data(),
315 input.extra_data() + input.extra_data_size());
316 config->extra_data.Swap(&data);
318 config->seek_preroll_usec = input.seek_preroll().InMicroseconds();
319 config->codec_delay = input.codec_delay();
320 return config.Pass();
324 media::AudioDecoderConfig
325 TypeConverter<media::AudioDecoderConfig, AudioDecoderConfigPtr>::Convert(
326 const AudioDecoderConfigPtr& input) {
327 media::AudioDecoderConfig config;
329 static_cast<media::AudioCodec>(input->codec),
330 static_cast<media::SampleFormat>(input->sample_format),
331 static_cast<media::ChannelLayout>(input->channel_layout),
332 input->samples_per_second,
333 input->extra_data.size() ? &input->extra_data.front() : NULL,
334 input->extra_data.size(),
337 base::TimeDelta::FromMicroseconds(input->seek_preroll_usec),
343 VideoDecoderConfigPtr
344 TypeConverter<VideoDecoderConfigPtr, media::VideoDecoderConfig>::Convert(
345 const media::VideoDecoderConfig& input) {
346 VideoDecoderConfigPtr config(VideoDecoderConfig::New());
347 config->codec = static_cast<VideoCodec>(input.codec());
348 config->profile = static_cast<VideoCodecProfile>(input.profile());
349 config->format = static_cast<VideoFormat>(input.format());
350 config->coded_size = Size::From(input.coded_size());
351 config->visible_rect = Rect::From(input.visible_rect());
352 config->natural_size = Size::From(input.natural_size());
353 if (input.extra_data()) {
354 std::vector<uint8> data(input.extra_data(),
355 input.extra_data() + input.extra_data_size());
356 config->extra_data.Swap(&data);
358 config->is_encrypted = input.is_encrypted();
359 return config.Pass();
363 media::VideoDecoderConfig
364 TypeConverter<media::VideoDecoderConfig, VideoDecoderConfigPtr>::Convert(
365 const VideoDecoderConfigPtr& input) {
366 media::VideoDecoderConfig config;
368 static_cast<media::VideoCodec>(input->codec),
369 static_cast<media::VideoCodecProfile>(input->profile),
370 static_cast<media::VideoFrame::Format>(input->format),
371 input->coded_size.To<gfx::Size>(),
372 input->visible_rect.To<gfx::Rect>(),
373 input->natural_size.To<gfx::Size>(),
374 input->extra_data.size() ? &input->extra_data.front() : NULL,
375 input->extra_data.size(),