Improve performance of registering font preferences
[chromium-blink-merge.git] / media / ffmpeg / ffmpeg_common.cc
blob6820066e52b250350025373e0045e3d019e4ebf3
1 // Copyright (c) 2012 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/ffmpeg/ffmpeg_common.h"
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "media/base/decoder_buffer.h"
10 #include "media/base/video_util.h"
12 namespace media {
14 // Why FF_INPUT_BUFFER_PADDING_SIZE? FFmpeg assumes all input buffers are
15 // padded. Check here to ensure FFmpeg only receives data padded to its
16 // specifications.
17 COMPILE_ASSERT(DecoderBuffer::kPaddingSize >= FF_INPUT_BUFFER_PADDING_SIZE,
18 decoder_buffer_padding_size_does_not_fit_ffmpeg_requirement);
20 // Alignment requirement by FFmpeg for input buffers. This need to be updated
21 // to match FFmpeg when it changes.
22 #if defined(ARCH_CPU_ARM_FAMILY)
23 static const int kFFmpegInputBufferAlignmentSize = 16;
24 #else
25 static const int kFFmpegInputBufferAlignmentSize = 32;
26 #endif
27 // Check here to ensure FFmpeg only receives data aligned to its specifications.
28 COMPILE_ASSERT(
29 DecoderBuffer::kAlignmentSize >= kFFmpegInputBufferAlignmentSize &&
30 DecoderBuffer::kAlignmentSize % kFFmpegInputBufferAlignmentSize == 0,
31 decoder_buffer_alignment_size_does_not_fit_ffmpeg_requirement);
33 static const AVRational kMicrosBase = { 1, base::Time::kMicrosecondsPerSecond };
35 base::TimeDelta ConvertFromTimeBase(const AVRational& time_base,
36 int64 timestamp) {
37 int64 microseconds = av_rescale_q(timestamp, time_base, kMicrosBase);
38 return base::TimeDelta::FromMicroseconds(microseconds);
41 int64 ConvertToTimeBase(const AVRational& time_base,
42 const base::TimeDelta& timestamp) {
43 return av_rescale_q(timestamp.InMicroseconds(), kMicrosBase, time_base);
46 AudioCodec CodecIDToAudioCodec(CodecID codec_id) {
47 switch (codec_id) {
48 case CODEC_ID_AAC:
49 return kCodecAAC;
50 case CODEC_ID_MP3:
51 return kCodecMP3;
52 case CODEC_ID_VORBIS:
53 return kCodecVorbis;
54 case CODEC_ID_PCM_U8:
55 case CODEC_ID_PCM_S16LE:
56 case CODEC_ID_PCM_S24LE:
57 return kCodecPCM;
58 case CODEC_ID_PCM_S16BE:
59 return kCodecPCM_S16BE;
60 case CODEC_ID_PCM_S24BE:
61 return kCodecPCM_S24BE;
62 case CODEC_ID_FLAC:
63 return kCodecFLAC;
64 case CODEC_ID_AMR_NB:
65 return kCodecAMR_NB;
66 case CODEC_ID_AMR_WB:
67 return kCodecAMR_WB;
68 case CODEC_ID_GSM_MS:
69 return kCodecGSM_MS;
70 case CODEC_ID_PCM_MULAW:
71 return kCodecPCM_MULAW;
72 default:
73 DVLOG(1) << "Unknown audio CodecID: " << codec_id;
75 return kUnknownAudioCodec;
78 static CodecID AudioCodecToCodecID(AudioCodec audio_codec,
79 int bits_per_channel) {
80 switch (audio_codec) {
81 case kCodecAAC:
82 return CODEC_ID_AAC;
83 case kCodecMP3:
84 return CODEC_ID_MP3;
85 case kCodecPCM:
86 switch (bits_per_channel) {
87 case 8:
88 return CODEC_ID_PCM_U8;
89 case 16:
90 return CODEC_ID_PCM_S16LE;
91 case 32:
92 return CODEC_ID_PCM_S24LE;
93 default:
94 DVLOG(1) << "Unsupported bits per channel: " << bits_per_channel;
96 break;
97 case kCodecPCM_S16BE:
98 return CODEC_ID_PCM_S16BE;
99 case kCodecPCM_S24BE:
100 return CODEC_ID_PCM_S24BE;
101 case kCodecVorbis:
102 return CODEC_ID_VORBIS;
103 case kCodecFLAC:
104 return CODEC_ID_FLAC;
105 case kCodecAMR_NB:
106 return CODEC_ID_AMR_NB;
107 case kCodecAMR_WB:
108 return CODEC_ID_AMR_WB;
109 case kCodecGSM_MS:
110 return CODEC_ID_GSM_MS;
111 case kCodecPCM_MULAW:
112 return CODEC_ID_PCM_MULAW;
113 default:
114 DVLOG(1) << "Unknown AudioCodec: " << audio_codec;
116 return CODEC_ID_NONE;
119 VideoCodec CodecIDToVideoCodec(CodecID codec_id) {
120 switch (codec_id) {
121 case CODEC_ID_VC1:
122 return kCodecVC1;
123 case CODEC_ID_H264:
124 return kCodecH264;
125 case CODEC_ID_THEORA:
126 return kCodecTheora;
127 case CODEC_ID_MPEG2VIDEO:
128 return kCodecMPEG2;
129 case CODEC_ID_MPEG4:
130 return kCodecMPEG4;
131 case CODEC_ID_VP8:
132 return kCodecVP8;
133 default:
134 DVLOG(1) << "Unknown video CodecID: " << codec_id;
136 return kUnknownVideoCodec;
139 static CodecID VideoCodecToCodecID(VideoCodec video_codec) {
140 switch (video_codec) {
141 case kCodecVC1:
142 return CODEC_ID_VC1;
143 case kCodecH264:
144 return CODEC_ID_H264;
145 case kCodecTheora:
146 return CODEC_ID_THEORA;
147 case kCodecMPEG2:
148 return CODEC_ID_MPEG2VIDEO;
149 case kCodecMPEG4:
150 return CODEC_ID_MPEG4;
151 case kCodecVP8:
152 return CODEC_ID_VP8;
153 default:
154 DVLOG(1) << "Unknown VideoCodec: " << video_codec;
156 return CODEC_ID_NONE;
159 static VideoCodecProfile ProfileIDToVideoCodecProfile(int profile) {
160 // Clear out the CONSTRAINED & INTRA flags which are strict subsets of the
161 // corresponding profiles with which they're used.
162 profile &= ~FF_PROFILE_H264_CONSTRAINED;
163 profile &= ~FF_PROFILE_H264_INTRA;
164 switch (profile) {
165 case FF_PROFILE_H264_BASELINE:
166 return H264PROFILE_BASELINE;
167 case FF_PROFILE_H264_MAIN:
168 return H264PROFILE_MAIN;
169 case FF_PROFILE_H264_EXTENDED:
170 return H264PROFILE_EXTENDED;
171 case FF_PROFILE_H264_HIGH:
172 return H264PROFILE_HIGH;
173 case FF_PROFILE_H264_HIGH_10:
174 return H264PROFILE_HIGH10PROFILE;
175 case FF_PROFILE_H264_HIGH_422:
176 return H264PROFILE_HIGH422PROFILE;
177 case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
178 return H264PROFILE_HIGH444PREDICTIVEPROFILE;
179 default:
180 DVLOG(1) << "Unknown profile id: " << profile;
182 return VIDEO_CODEC_PROFILE_UNKNOWN;
185 static int VideoCodecProfileToProfileID(VideoCodecProfile profile) {
186 switch (profile) {
187 case H264PROFILE_BASELINE:
188 return FF_PROFILE_H264_BASELINE;
189 case H264PROFILE_MAIN:
190 return FF_PROFILE_H264_MAIN;
191 case H264PROFILE_EXTENDED:
192 return FF_PROFILE_H264_EXTENDED;
193 case H264PROFILE_HIGH:
194 return FF_PROFILE_H264_HIGH;
195 case H264PROFILE_HIGH10PROFILE:
196 return FF_PROFILE_H264_HIGH_10;
197 case H264PROFILE_HIGH422PROFILE:
198 return FF_PROFILE_H264_HIGH_422;
199 case H264PROFILE_HIGH444PREDICTIVEPROFILE:
200 return FF_PROFILE_H264_HIGH_444_PREDICTIVE;
201 default:
202 DVLOG(1) << "Unknown VideoCodecProfile: " << profile;
204 return FF_PROFILE_UNKNOWN;
207 void AVCodecContextToAudioDecoderConfig(
208 const AVCodecContext* codec_context,
209 AudioDecoderConfig* config) {
210 DCHECK_EQ(codec_context->codec_type, AVMEDIA_TYPE_AUDIO);
212 AudioCodec codec = CodecIDToAudioCodec(codec_context->codec_id);
213 int bytes_per_channel = av_get_bytes_per_sample(codec_context->sample_fmt);
214 ChannelLayout channel_layout =
215 ChannelLayoutToChromeChannelLayout(codec_context->channel_layout,
216 codec_context->channels);
217 int samples_per_second = codec_context->sample_rate;
219 config->Initialize(codec,
220 bytes_per_channel << 3,
221 channel_layout,
222 samples_per_second,
223 codec_context->extradata,
224 codec_context->extradata_size,
225 false, // Not encrypted.
226 true);
229 void AudioDecoderConfigToAVCodecContext(const AudioDecoderConfig& config,
230 AVCodecContext* codec_context) {
231 codec_context->codec_type = AVMEDIA_TYPE_AUDIO;
232 codec_context->codec_id = AudioCodecToCodecID(config.codec(),
233 config.bits_per_channel());
235 switch (config.bits_per_channel()) {
236 case 8:
237 codec_context->sample_fmt = AV_SAMPLE_FMT_U8;
238 break;
239 case 16:
240 codec_context->sample_fmt = AV_SAMPLE_FMT_S16;
241 break;
242 case 32:
243 codec_context->sample_fmt = AV_SAMPLE_FMT_S32;
244 break;
245 default:
246 DVLOG(1) << "Unsupported bits per channel: " << config.bits_per_channel();
247 codec_context->sample_fmt = AV_SAMPLE_FMT_NONE;
250 // TODO(scherkus): should we set |channel_layout|? I'm not sure if FFmpeg uses
251 // said information to decode.
252 codec_context->channels =
253 ChannelLayoutToChannelCount(config.channel_layout());
254 codec_context->sample_rate = config.samples_per_second();
256 if (config.extra_data()) {
257 codec_context->extradata_size = config.extra_data_size();
258 codec_context->extradata = reinterpret_cast<uint8_t*>(
259 av_malloc(config.extra_data_size() + FF_INPUT_BUFFER_PADDING_SIZE));
260 memcpy(codec_context->extradata, config.extra_data(),
261 config.extra_data_size());
262 memset(codec_context->extradata + config.extra_data_size(), '\0',
263 FF_INPUT_BUFFER_PADDING_SIZE);
264 } else {
265 codec_context->extradata = NULL;
266 codec_context->extradata_size = 0;
270 void AVStreamToVideoDecoderConfig(
271 const AVStream* stream,
272 VideoDecoderConfig* config) {
273 gfx::Size coded_size(stream->codec->coded_width, stream->codec->coded_height);
275 // TODO(vrk): This assumes decoded frame data starts at (0, 0), which is true
276 // for now, but may not always be true forever. Fix this in the future.
277 gfx::Rect visible_rect(stream->codec->width, stream->codec->height);
279 AVRational aspect_ratio = { 1, 1 };
280 if (stream->sample_aspect_ratio.num)
281 aspect_ratio = stream->sample_aspect_ratio;
282 else if (stream->codec->sample_aspect_ratio.num)
283 aspect_ratio = stream->codec->sample_aspect_ratio;
285 VideoCodec codec = CodecIDToVideoCodec(stream->codec->codec_id);
286 VideoCodecProfile profile = (codec == kCodecVP8) ? VP8PROFILE_MAIN :
287 ProfileIDToVideoCodecProfile(stream->codec->profile);
288 gfx::Size natural_size = GetNaturalSize(
289 visible_rect.size(), aspect_ratio.num, aspect_ratio.den);
290 config->Initialize(codec,
291 profile,
292 PixelFormatToVideoFormat(stream->codec->pix_fmt),
293 coded_size, visible_rect, natural_size,
294 stream->codec->extradata, stream->codec->extradata_size,
295 false, // Not encrypted.
296 true);
299 void VideoDecoderConfigToAVCodecContext(
300 const VideoDecoderConfig& config,
301 AVCodecContext* codec_context) {
302 codec_context->codec_type = AVMEDIA_TYPE_VIDEO;
303 codec_context->codec_id = VideoCodecToCodecID(config.codec());
304 codec_context->profile = VideoCodecProfileToProfileID(config.profile());
305 codec_context->coded_width = config.coded_size().width();
306 codec_context->coded_height = config.coded_size().height();
307 codec_context->pix_fmt = VideoFormatToPixelFormat(config.format());
309 if (config.extra_data()) {
310 codec_context->extradata_size = config.extra_data_size();
311 codec_context->extradata = reinterpret_cast<uint8_t*>(
312 av_malloc(config.extra_data_size() + FF_INPUT_BUFFER_PADDING_SIZE));
313 memcpy(codec_context->extradata, config.extra_data(),
314 config.extra_data_size());
315 memset(codec_context->extradata + config.extra_data_size(), '\0',
316 FF_INPUT_BUFFER_PADDING_SIZE);
317 } else {
318 codec_context->extradata = NULL;
319 codec_context->extradata_size = 0;
323 ChannelLayout ChannelLayoutToChromeChannelLayout(int64_t layout,
324 int channels) {
325 switch (layout) {
326 case AV_CH_LAYOUT_MONO:
327 return CHANNEL_LAYOUT_MONO;
328 case AV_CH_LAYOUT_STEREO:
329 return CHANNEL_LAYOUT_STEREO;
330 case AV_CH_LAYOUT_2_1:
331 return CHANNEL_LAYOUT_2_1;
332 case AV_CH_LAYOUT_SURROUND:
333 return CHANNEL_LAYOUT_SURROUND;
334 case AV_CH_LAYOUT_4POINT0:
335 return CHANNEL_LAYOUT_4_0;
336 case AV_CH_LAYOUT_2_2:
337 return CHANNEL_LAYOUT_2_2;
338 case AV_CH_LAYOUT_QUAD:
339 return CHANNEL_LAYOUT_QUAD;
340 case AV_CH_LAYOUT_5POINT0:
341 return CHANNEL_LAYOUT_5_0;
342 case AV_CH_LAYOUT_5POINT1:
343 return CHANNEL_LAYOUT_5_1;
344 case AV_CH_LAYOUT_5POINT0_BACK:
345 return CHANNEL_LAYOUT_5_0_BACK;
346 case AV_CH_LAYOUT_5POINT1_BACK:
347 return CHANNEL_LAYOUT_5_1_BACK;
348 case AV_CH_LAYOUT_7POINT0:
349 return CHANNEL_LAYOUT_7_0;
350 case AV_CH_LAYOUT_7POINT1:
351 return CHANNEL_LAYOUT_7_1;
352 case AV_CH_LAYOUT_7POINT1_WIDE:
353 return CHANNEL_LAYOUT_7_1_WIDE;
354 case AV_CH_LAYOUT_STEREO_DOWNMIX:
355 return CHANNEL_LAYOUT_STEREO_DOWNMIX;
356 case AV_CH_LAYOUT_2POINT1:
357 return CHANNEL_LAYOUT_2POINT1;
358 case AV_CH_LAYOUT_3POINT1:
359 return CHANNEL_LAYOUT_3_1;
360 case AV_CH_LAYOUT_4POINT1:
361 return CHANNEL_LAYOUT_4_1;
362 case AV_CH_LAYOUT_6POINT0:
363 return CHANNEL_LAYOUT_6_0;
364 case AV_CH_LAYOUT_6POINT0_FRONT:
365 return CHANNEL_LAYOUT_6_0_FRONT;
366 case AV_CH_LAYOUT_HEXAGONAL:
367 return CHANNEL_LAYOUT_HEXAGONAL;
368 case AV_CH_LAYOUT_6POINT1:
369 return CHANNEL_LAYOUT_6_1;
370 case AV_CH_LAYOUT_6POINT1_BACK:
371 return CHANNEL_LAYOUT_6_1_BACK;
372 case AV_CH_LAYOUT_6POINT1_FRONT:
373 return CHANNEL_LAYOUT_6_1_FRONT;
374 case AV_CH_LAYOUT_7POINT0_FRONT:
375 return CHANNEL_LAYOUT_7_0_FRONT;
376 case AV_CH_LAYOUT_7POINT1_WIDE_BACK:
377 return CHANNEL_LAYOUT_7_1_WIDE_BACK;
378 case AV_CH_LAYOUT_OCTAGONAL:
379 return CHANNEL_LAYOUT_OCTAGONAL;
380 default:
381 // FFmpeg channel_layout is 0 for .wav and .mp3. We know mono and stereo
382 // from the number of channels, otherwise report errors.
383 if (channels == 1)
384 return CHANNEL_LAYOUT_MONO;
385 if (channels == 2)
386 return CHANNEL_LAYOUT_STEREO;
387 LOG(ERROR) << "Unsupported channel layout: " << layout;
389 return CHANNEL_LAYOUT_UNSUPPORTED;
392 VideoFrame::Format PixelFormatToVideoFormat(PixelFormat pixel_format) {
393 switch (pixel_format) {
394 case PIX_FMT_YUV422P:
395 return VideoFrame::YV16;
396 case PIX_FMT_YUV420P:
397 return VideoFrame::YV12;
398 default:
399 DVLOG(1) << "Unsupported PixelFormat: " << pixel_format;
401 return VideoFrame::INVALID;
404 PixelFormat VideoFormatToPixelFormat(VideoFrame::Format video_format) {
405 switch (video_format) {
406 case VideoFrame::YV16:
407 return PIX_FMT_YUV422P;
408 case VideoFrame::YV12:
409 return PIX_FMT_YUV420P;
410 default:
411 DVLOG(1) << "Unsupported VideoFrame::Format: " << video_format;
413 return PIX_FMT_NONE;
416 void DestroyAVFormatContext(AVFormatContext* format_context) {
417 DCHECK(format_context);
419 // Iterate each stream and destroy each one of them.
420 if (format_context->streams) {
421 int streams = format_context->nb_streams;
422 for (int i = 0; i < streams; ++i) {
423 AVStream* stream = format_context->streams[i];
425 // The conditions for calling avcodec_close():
426 // 1. AVStream is alive.
427 // 2. AVCodecContext in AVStream is alive.
428 // 3. AVCodec in AVCodecContext is alive.
429 // Notice that closing a codec context without prior avcodec_open2() will
430 // result in a crash in FFmpeg.
431 if (stream && stream->codec && stream->codec->codec) {
432 stream->discard = AVDISCARD_ALL;
433 avcodec_close(stream->codec);
438 // Then finally cleanup the format context.
439 avformat_close_input(&format_context);
442 } // namespace media