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"
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
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;
25 static const int kFFmpegInputBufferAlignmentSize
= 32;
27 // Check here to ensure FFmpeg only receives data aligned to its specifications.
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
,
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
) {
55 case CODEC_ID_PCM_S16LE
:
56 case CODEC_ID_PCM_S24LE
:
58 case CODEC_ID_PCM_S16BE
:
59 return kCodecPCM_S16BE
;
60 case CODEC_ID_PCM_S24BE
:
61 return kCodecPCM_S24BE
;
70 case CODEC_ID_PCM_MULAW
:
71 return kCodecPCM_MULAW
;
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
) {
86 switch (bits_per_channel
) {
88 return CODEC_ID_PCM_U8
;
90 return CODEC_ID_PCM_S16LE
;
92 return CODEC_ID_PCM_S24LE
;
94 DVLOG(1) << "Unsupported bits per channel: " << bits_per_channel
;
98 return CODEC_ID_PCM_S16BE
;
100 return CODEC_ID_PCM_S24BE
;
102 return CODEC_ID_VORBIS
;
104 return CODEC_ID_FLAC
;
106 return CODEC_ID_AMR_NB
;
108 return CODEC_ID_AMR_WB
;
110 return CODEC_ID_GSM_MS
;
111 case kCodecPCM_MULAW
:
112 return CODEC_ID_PCM_MULAW
;
114 DVLOG(1) << "Unknown AudioCodec: " << audio_codec
;
116 return CODEC_ID_NONE
;
119 VideoCodec
CodecIDToVideoCodec(CodecID codec_id
) {
125 case CODEC_ID_THEORA
:
127 case CODEC_ID_MPEG2VIDEO
:
134 DVLOG(1) << "Unknown video CodecID: " << codec_id
;
136 return kUnknownVideoCodec
;
139 static CodecID
VideoCodecToCodecID(VideoCodec video_codec
) {
140 switch (video_codec
) {
144 return CODEC_ID_H264
;
146 return CODEC_ID_THEORA
;
148 return CODEC_ID_MPEG2VIDEO
;
150 return CODEC_ID_MPEG4
;
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
;
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
;
180 DVLOG(1) << "Unknown profile id: " << profile
;
182 return VIDEO_CODEC_PROFILE_UNKNOWN
;
185 static int VideoCodecProfileToProfileID(VideoCodecProfile 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
;
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,
223 codec_context
->extradata
,
224 codec_context
->extradata_size
,
225 false, // Not encrypted.
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()) {
237 codec_context
->sample_fmt
= AV_SAMPLE_FMT_U8
;
240 codec_context
->sample_fmt
= AV_SAMPLE_FMT_S16
;
243 codec_context
->sample_fmt
= AV_SAMPLE_FMT_S32
;
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
);
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
,
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.
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
);
318 codec_context
->extradata
= NULL
;
319 codec_context
->extradata_size
= 0;
323 ChannelLayout
ChannelLayoutToChromeChannelLayout(int64_t 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
;
381 // FFmpeg channel_layout is 0 for .wav and .mp3. We know mono and stereo
382 // from the number of channels, otherwise report errors.
384 return CHANNEL_LAYOUT_MONO
;
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
;
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
;
411 DVLOG(1) << "Unsupported VideoFrame::Format: " << video_format
;
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
);