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 "base/metrics/histogram.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_split.h"
12 #include "base/strings/string_util.h"
13 #include "media/base/decoder_buffer.h"
14 #include "media/base/video_decoder_config.h"
15 #include "media/base/video_util.h"
19 // Why FF_INPUT_BUFFER_PADDING_SIZE? FFmpeg assumes all input buffers are
20 // padded. Check here to ensure FFmpeg only receives data padded to its
22 static_assert(DecoderBuffer::kPaddingSize
>= FF_INPUT_BUFFER_PADDING_SIZE
,
23 "DecoderBuffer padding size does not fit ffmpeg requirement");
25 // Alignment requirement by FFmpeg for input and output buffers. This need to
26 // be updated to match FFmpeg when it changes.
27 #if defined(ARCH_CPU_ARM_FAMILY)
28 static const int kFFmpegBufferAddressAlignment
= 16;
30 static const int kFFmpegBufferAddressAlignment
= 32;
33 // Check here to ensure FFmpeg only receives data aligned to its specifications.
35 DecoderBuffer::kAlignmentSize
>= kFFmpegBufferAddressAlignment
&&
36 DecoderBuffer::kAlignmentSize
% kFFmpegBufferAddressAlignment
== 0,
37 "DecoderBuffer alignment size does not fit ffmpeg requirement");
39 // Allows faster SIMD YUV convert. Also, FFmpeg overreads/-writes occasionally.
40 // See video_get_buffer() in libavcodec/utils.c.
41 static const int kFFmpegOutputBufferPaddingSize
= 16;
43 static_assert(VideoFrame::kFrameSizePadding
>= kFFmpegOutputBufferPaddingSize
,
44 "VideoFrame padding size does not fit ffmpeg requirement");
47 VideoFrame::kFrameAddressAlignment
>= kFFmpegBufferAddressAlignment
&&
48 VideoFrame::kFrameAddressAlignment
% kFFmpegBufferAddressAlignment
== 0,
49 "VideoFrame frame address alignment does not fit ffmpeg requirement");
51 static const AVRational kMicrosBase
= { 1, base::Time::kMicrosecondsPerSecond
};
53 base::TimeDelta
ConvertFromTimeBase(const AVRational
& time_base
,
55 int64 microseconds
= av_rescale_q(timestamp
, time_base
, kMicrosBase
);
56 return base::TimeDelta::FromMicroseconds(microseconds
);
59 int64
ConvertToTimeBase(const AVRational
& time_base
,
60 const base::TimeDelta
& timestamp
) {
61 return av_rescale_q(timestamp
.InMicroseconds(), kMicrosBase
, time_base
);
64 // Converts an FFmpeg audio codec ID into its corresponding supported codec id.
65 static AudioCodec
CodecIDToAudioCodec(AVCodecID codec_id
) {
71 case AV_CODEC_ID_VORBIS
:
73 case AV_CODEC_ID_PCM_U8
:
74 case AV_CODEC_ID_PCM_S16LE
:
75 case AV_CODEC_ID_PCM_S24LE
:
76 case AV_CODEC_ID_PCM_F32LE
:
78 case AV_CODEC_ID_PCM_S16BE
:
79 return kCodecPCM_S16BE
;
80 case AV_CODEC_ID_PCM_S24BE
:
81 return kCodecPCM_S24BE
;
82 case AV_CODEC_ID_FLAC
:
84 case AV_CODEC_ID_AMR_NB
:
86 case AV_CODEC_ID_AMR_WB
:
88 case AV_CODEC_ID_GSM_MS
:
90 case AV_CODEC_ID_PCM_ALAW
:
91 return kCodecPCM_ALAW
;
92 case AV_CODEC_ID_PCM_MULAW
:
93 return kCodecPCM_MULAW
;
94 case AV_CODEC_ID_OPUS
:
96 case AV_CODEC_ID_ALAC
:
99 DVLOG(1) << "Unknown audio CodecID: " << codec_id
;
101 return kUnknownAudioCodec
;
104 static AVCodecID
AudioCodecToCodecID(AudioCodec audio_codec
,
105 SampleFormat sample_format
) {
106 switch (audio_codec
) {
108 return AV_CODEC_ID_AAC
;
110 return AV_CODEC_ID_ALAC
;
112 return AV_CODEC_ID_MP3
;
114 switch (sample_format
) {
115 case kSampleFormatU8
:
116 return AV_CODEC_ID_PCM_U8
;
117 case kSampleFormatS16
:
118 return AV_CODEC_ID_PCM_S16LE
;
119 case kSampleFormatS32
:
120 return AV_CODEC_ID_PCM_S24LE
;
121 case kSampleFormatF32
:
122 return AV_CODEC_ID_PCM_F32LE
;
124 DVLOG(1) << "Unsupported sample format: " << sample_format
;
127 case kCodecPCM_S16BE
:
128 return AV_CODEC_ID_PCM_S16BE
;
129 case kCodecPCM_S24BE
:
130 return AV_CODEC_ID_PCM_S24BE
;
132 return AV_CODEC_ID_VORBIS
;
134 return AV_CODEC_ID_FLAC
;
136 return AV_CODEC_ID_AMR_NB
;
138 return AV_CODEC_ID_AMR_WB
;
140 return AV_CODEC_ID_GSM_MS
;
142 return AV_CODEC_ID_PCM_ALAW
;
143 case kCodecPCM_MULAW
:
144 return AV_CODEC_ID_PCM_MULAW
;
146 return AV_CODEC_ID_OPUS
;
148 DVLOG(1) << "Unknown AudioCodec: " << audio_codec
;
150 return AV_CODEC_ID_NONE
;
153 // Converts an FFmpeg video codec ID into its corresponding supported codec id.
154 static VideoCodec
CodecIDToVideoCodec(AVCodecID codec_id
) {
156 case AV_CODEC_ID_H264
:
158 #if defined(ENABLE_HEVC_DEMUXING)
159 case AV_CODEC_ID_HEVC
:
162 case AV_CODEC_ID_THEORA
:
164 case AV_CODEC_ID_MPEG4
:
166 case AV_CODEC_ID_VP8
:
168 case AV_CODEC_ID_VP9
:
171 DVLOG(1) << "Unknown video CodecID: " << codec_id
;
173 return kUnknownVideoCodec
;
176 AVCodecID
VideoCodecToCodecID(VideoCodec video_codec
) {
177 switch (video_codec
) {
179 return AV_CODEC_ID_H264
;
180 #if defined(ENABLE_HEVC_DEMUXING)
182 return AV_CODEC_ID_HEVC
;
185 return AV_CODEC_ID_THEORA
;
187 return AV_CODEC_ID_MPEG4
;
189 return AV_CODEC_ID_VP8
;
191 return AV_CODEC_ID_VP9
;
193 DVLOG(1) << "Unknown VideoCodec: " << video_codec
;
195 return AV_CODEC_ID_NONE
;
198 static VideoCodecProfile
ProfileIDToVideoCodecProfile(int profile
) {
199 // Clear out the CONSTRAINED & INTRA flags which are strict subsets of the
200 // corresponding profiles with which they're used.
201 profile
&= ~FF_PROFILE_H264_CONSTRAINED
;
202 profile
&= ~FF_PROFILE_H264_INTRA
;
204 case FF_PROFILE_H264_BASELINE
:
205 return H264PROFILE_BASELINE
;
206 case FF_PROFILE_H264_MAIN
:
207 return H264PROFILE_MAIN
;
208 case FF_PROFILE_H264_EXTENDED
:
209 return H264PROFILE_EXTENDED
;
210 case FF_PROFILE_H264_HIGH
:
211 return H264PROFILE_HIGH
;
212 case FF_PROFILE_H264_HIGH_10
:
213 return H264PROFILE_HIGH10PROFILE
;
214 case FF_PROFILE_H264_HIGH_422
:
215 return H264PROFILE_HIGH422PROFILE
;
216 case FF_PROFILE_H264_HIGH_444_PREDICTIVE
:
217 return H264PROFILE_HIGH444PREDICTIVEPROFILE
;
219 DVLOG(1) << "Unknown profile id: " << profile
;
221 return VIDEO_CODEC_PROFILE_UNKNOWN
;
224 static int VideoCodecProfileToProfileID(VideoCodecProfile profile
) {
226 case H264PROFILE_BASELINE
:
227 return FF_PROFILE_H264_BASELINE
;
228 case H264PROFILE_MAIN
:
229 return FF_PROFILE_H264_MAIN
;
230 case H264PROFILE_EXTENDED
:
231 return FF_PROFILE_H264_EXTENDED
;
232 case H264PROFILE_HIGH
:
233 return FF_PROFILE_H264_HIGH
;
234 case H264PROFILE_HIGH10PROFILE
:
235 return FF_PROFILE_H264_HIGH_10
;
236 case H264PROFILE_HIGH422PROFILE
:
237 return FF_PROFILE_H264_HIGH_422
;
238 case H264PROFILE_HIGH444PREDICTIVEPROFILE
:
239 return FF_PROFILE_H264_HIGH_444_PREDICTIVE
;
241 DVLOG(1) << "Unknown VideoCodecProfile: " << profile
;
243 return FF_PROFILE_UNKNOWN
;
246 SampleFormat
AVSampleFormatToSampleFormat(AVSampleFormat sample_format
) {
247 switch (sample_format
) {
248 case AV_SAMPLE_FMT_U8
:
249 return kSampleFormatU8
;
250 case AV_SAMPLE_FMT_S16
:
251 return kSampleFormatS16
;
252 case AV_SAMPLE_FMT_S32
:
253 return kSampleFormatS32
;
254 case AV_SAMPLE_FMT_FLT
:
255 return kSampleFormatF32
;
256 case AV_SAMPLE_FMT_S16P
:
257 return kSampleFormatPlanarS16
;
258 case AV_SAMPLE_FMT_S32P
:
259 return kSampleFormatPlanarS32
;
260 case AV_SAMPLE_FMT_FLTP
:
261 return kSampleFormatPlanarF32
;
263 DVLOG(1) << "Unknown AVSampleFormat: " << sample_format
;
265 return kUnknownSampleFormat
;
268 static AVSampleFormat
SampleFormatToAVSampleFormat(SampleFormat sample_format
) {
269 switch (sample_format
) {
270 case kSampleFormatU8
:
271 return AV_SAMPLE_FMT_U8
;
272 case kSampleFormatS16
:
273 return AV_SAMPLE_FMT_S16
;
274 case kSampleFormatS32
:
275 return AV_SAMPLE_FMT_S32
;
276 case kSampleFormatF32
:
277 return AV_SAMPLE_FMT_FLT
;
278 case kSampleFormatPlanarS16
:
279 return AV_SAMPLE_FMT_S16P
;
280 case kSampleFormatPlanarF32
:
281 return AV_SAMPLE_FMT_FLTP
;
283 DVLOG(1) << "Unknown SampleFormat: " << sample_format
;
285 return AV_SAMPLE_FMT_NONE
;
288 void AVCodecContextToAudioDecoderConfig(const AVCodecContext
* codec_context
,
290 AudioDecoderConfig
* config
) {
291 DCHECK_EQ(codec_context
->codec_type
, AVMEDIA_TYPE_AUDIO
);
293 AudioCodec codec
= CodecIDToAudioCodec(codec_context
->codec_id
);
295 SampleFormat sample_format
=
296 AVSampleFormatToSampleFormat(codec_context
->sample_fmt
);
298 ChannelLayout channel_layout
= ChannelLayoutToChromeChannelLayout(
299 codec_context
->channel_layout
, codec_context
->channels
);
301 int sample_rate
= codec_context
->sample_rate
;
302 if (codec
== kCodecOpus
) {
303 // |codec_context->sample_fmt| is not set by FFmpeg because Opus decoding is
304 // not enabled in FFmpeg. It doesn't matter what value is set here, so long
305 // as it's valid, the true sample format is selected inside the decoder.
306 sample_format
= kSampleFormatF32
;
308 // Always use 48kHz for OPUS. Technically we should match to the highest
309 // supported hardware sample rate among [8, 12, 16, 24, 48] kHz, but we
310 // don't know the hardware sample rate at this point and those rates are
311 // rarely used for output. See the "Input Sample Rate" section of the spec:
312 // http://tools.ietf.org/html/draft-terriberry-oggopus-01#page-11
316 base::TimeDelta seek_preroll
;
317 if (codec_context
->seek_preroll
> 0) {
318 seek_preroll
= base::TimeDelta::FromMicroseconds(
319 codec_context
->seek_preroll
* 1000000.0 / codec_context
->sample_rate
);
322 config
->Initialize(codec
,
326 codec_context
->extradata
,
327 codec_context
->extradata_size
,
330 codec_context
->delay
);
332 if (codec
!= kCodecOpus
) {
333 DCHECK_EQ(av_get_bytes_per_sample(codec_context
->sample_fmt
) * 8,
334 config
->bits_per_channel());
338 void AVStreamToAudioDecoderConfig(const AVStream
* stream
,
339 AudioDecoderConfig
* config
) {
340 bool is_encrypted
= false;
341 AVDictionaryEntry
* key
= av_dict_get(stream
->metadata
, "enc_key_id", NULL
, 0);
344 AVCodecContextToAudioDecoderConfig(stream
->codec
, is_encrypted
, config
);
347 void AudioDecoderConfigToAVCodecContext(const AudioDecoderConfig
& config
,
348 AVCodecContext
* codec_context
) {
349 codec_context
->codec_type
= AVMEDIA_TYPE_AUDIO
;
350 codec_context
->codec_id
= AudioCodecToCodecID(config
.codec(),
351 config
.sample_format());
352 codec_context
->sample_fmt
= SampleFormatToAVSampleFormat(
353 config
.sample_format());
355 // TODO(scherkus): should we set |channel_layout|? I'm not sure if FFmpeg uses
356 // said information to decode.
357 codec_context
->channels
=
358 ChannelLayoutToChannelCount(config
.channel_layout());
359 codec_context
->sample_rate
= config
.samples_per_second();
361 if (config
.extra_data()) {
362 codec_context
->extradata_size
= config
.extra_data_size();
363 codec_context
->extradata
= reinterpret_cast<uint8_t*>(
364 av_malloc(config
.extra_data_size() + FF_INPUT_BUFFER_PADDING_SIZE
));
365 memcpy(codec_context
->extradata
, config
.extra_data(),
366 config
.extra_data_size());
367 memset(codec_context
->extradata
+ config
.extra_data_size(), '\0',
368 FF_INPUT_BUFFER_PADDING_SIZE
);
370 codec_context
->extradata
= NULL
;
371 codec_context
->extradata_size
= 0;
375 void AVStreamToVideoDecoderConfig(const AVStream
* stream
,
376 VideoDecoderConfig
* config
) {
377 gfx::Size
coded_size(stream
->codec
->coded_width
, stream
->codec
->coded_height
);
379 // TODO(vrk): This assumes decoded frame data starts at (0, 0), which is true
380 // for now, but may not always be true forever. Fix this in the future.
381 gfx::Rect
visible_rect(stream
->codec
->width
, stream
->codec
->height
);
383 AVRational aspect_ratio
= { 1, 1 };
384 if (stream
->sample_aspect_ratio
.num
)
385 aspect_ratio
= stream
->sample_aspect_ratio
;
386 else if (stream
->codec
->sample_aspect_ratio
.num
)
387 aspect_ratio
= stream
->codec
->sample_aspect_ratio
;
389 VideoCodec codec
= CodecIDToVideoCodec(stream
->codec
->codec_id
);
391 VideoCodecProfile profile
= VIDEO_CODEC_PROFILE_UNKNOWN
;
392 if (codec
== kCodecVP8
)
393 profile
= VP8PROFILE_ANY
;
394 else if (codec
== kCodecVP9
)
395 profile
= VP9PROFILE_ANY
;
397 profile
= ProfileIDToVideoCodecProfile(stream
->codec
->profile
);
399 // Without the FFmpeg h264 decoder, AVFormat is unable to get the profile, so
400 // default to baseline and let the VDA fail later if it doesn't support the
401 // real profile. This is alright because if the FFmpeg h264 decoder isn't
402 // enabled, there is no fallback if the VDA fails.
403 #if defined(DISABLE_FFMPEG_VIDEO_DECODERS)
404 if (codec
== kCodecH264
)
405 profile
= H264PROFILE_BASELINE
;
408 gfx::Size natural_size
= GetNaturalSize(
409 visible_rect
.size(), aspect_ratio
.num
, aspect_ratio
.den
);
411 VideoPixelFormat format
=
412 AVPixelFormatToVideoPixelFormat(stream
->codec
->pix_fmt
);
413 // The format and coded size may be unknown if FFmpeg is compiled without
415 #if defined(DISABLE_FFMPEG_VIDEO_DECODERS)
416 if (format
== PIXEL_FORMAT_UNKNOWN
)
417 format
= PIXEL_FORMAT_YV12
;
418 if (coded_size
== gfx::Size(0, 0))
419 coded_size
= visible_rect
.size();
422 if (codec
== kCodecVP9
) {
423 // TODO(tomfinegan): libavcodec doesn't know about VP9.
424 format
= PIXEL_FORMAT_YV12
;
425 coded_size
= visible_rect
.size();
428 // Pad out |coded_size| for subsampled YUV formats.
429 if (format
!= PIXEL_FORMAT_YV24
) {
430 coded_size
.set_width((coded_size
.width() + 1) / 2 * 2);
431 if (format
!= PIXEL_FORMAT_YV16
)
432 coded_size
.set_height((coded_size
.height() + 1) / 2 * 2);
435 bool is_encrypted
= false;
436 AVDictionaryEntry
* key
= av_dict_get(stream
->metadata
, "enc_key_id", NULL
, 0);
440 AVDictionaryEntry
* webm_alpha
=
441 av_dict_get(stream
->metadata
, "alpha_mode", NULL
, 0);
442 if (webm_alpha
&& !strcmp(webm_alpha
->value
, "1")) {
443 format
= PIXEL_FORMAT_YV12A
;
446 // Prefer the color space found by libavcodec if available.
447 ColorSpace color_space
= AVColorSpaceToColorSpace(stream
->codec
->colorspace
,
448 stream
->codec
->color_range
);
449 if (color_space
== COLOR_SPACE_UNSPECIFIED
) {
450 // Otherwise, assume that SD video is usually Rec.601, and HD is usually
452 color_space
= (natural_size
.height() < 720) ? COLOR_SPACE_SD_REC601
453 : COLOR_SPACE_HD_REC709
;
456 config
->Initialize(codec
, profile
, format
, color_space
, coded_size
,
457 visible_rect
, natural_size
, stream
->codec
->extradata
,
458 stream
->codec
->extradata_size
, is_encrypted
);
461 void VideoDecoderConfigToAVCodecContext(
462 const VideoDecoderConfig
& config
,
463 AVCodecContext
* codec_context
) {
464 codec_context
->codec_type
= AVMEDIA_TYPE_VIDEO
;
465 codec_context
->codec_id
= VideoCodecToCodecID(config
.codec());
466 codec_context
->profile
= VideoCodecProfileToProfileID(config
.profile());
467 codec_context
->coded_width
= config
.coded_size().width();
468 codec_context
->coded_height
= config
.coded_size().height();
469 codec_context
->pix_fmt
= VideoPixelFormatToAVPixelFormat(config
.format());
470 if (config
.color_space() == COLOR_SPACE_JPEG
)
471 codec_context
->color_range
= AVCOL_RANGE_JPEG
;
473 if (config
.extra_data()) {
474 codec_context
->extradata_size
= config
.extra_data_size();
475 codec_context
->extradata
= reinterpret_cast<uint8_t*>(
476 av_malloc(config
.extra_data_size() + FF_INPUT_BUFFER_PADDING_SIZE
));
477 memcpy(codec_context
->extradata
, config
.extra_data(),
478 config
.extra_data_size());
479 memset(codec_context
->extradata
+ config
.extra_data_size(), '\0',
480 FF_INPUT_BUFFER_PADDING_SIZE
);
482 codec_context
->extradata
= NULL
;
483 codec_context
->extradata_size
= 0;
487 ChannelLayout
ChannelLayoutToChromeChannelLayout(int64_t layout
, int channels
) {
489 case AV_CH_LAYOUT_MONO
:
490 return CHANNEL_LAYOUT_MONO
;
491 case AV_CH_LAYOUT_STEREO
:
492 return CHANNEL_LAYOUT_STEREO
;
493 case AV_CH_LAYOUT_2_1
:
494 return CHANNEL_LAYOUT_2_1
;
495 case AV_CH_LAYOUT_SURROUND
:
496 return CHANNEL_LAYOUT_SURROUND
;
497 case AV_CH_LAYOUT_4POINT0
:
498 return CHANNEL_LAYOUT_4_0
;
499 case AV_CH_LAYOUT_2_2
:
500 return CHANNEL_LAYOUT_2_2
;
501 case AV_CH_LAYOUT_QUAD
:
502 return CHANNEL_LAYOUT_QUAD
;
503 case AV_CH_LAYOUT_5POINT0
:
504 return CHANNEL_LAYOUT_5_0
;
505 case AV_CH_LAYOUT_5POINT1
:
506 return CHANNEL_LAYOUT_5_1
;
507 case AV_CH_LAYOUT_5POINT0_BACK
:
508 return CHANNEL_LAYOUT_5_0_BACK
;
509 case AV_CH_LAYOUT_5POINT1_BACK
:
510 return CHANNEL_LAYOUT_5_1_BACK
;
511 case AV_CH_LAYOUT_7POINT0
:
512 return CHANNEL_LAYOUT_7_0
;
513 case AV_CH_LAYOUT_7POINT1
:
514 return CHANNEL_LAYOUT_7_1
;
515 case AV_CH_LAYOUT_7POINT1_WIDE
:
516 return CHANNEL_LAYOUT_7_1_WIDE
;
517 case AV_CH_LAYOUT_STEREO_DOWNMIX
:
518 return CHANNEL_LAYOUT_STEREO_DOWNMIX
;
519 case AV_CH_LAYOUT_2POINT1
:
520 return CHANNEL_LAYOUT_2POINT1
;
521 case AV_CH_LAYOUT_3POINT1
:
522 return CHANNEL_LAYOUT_3_1
;
523 case AV_CH_LAYOUT_4POINT1
:
524 return CHANNEL_LAYOUT_4_1
;
525 case AV_CH_LAYOUT_6POINT0
:
526 return CHANNEL_LAYOUT_6_0
;
527 case AV_CH_LAYOUT_6POINT0_FRONT
:
528 return CHANNEL_LAYOUT_6_0_FRONT
;
529 case AV_CH_LAYOUT_HEXAGONAL
:
530 return CHANNEL_LAYOUT_HEXAGONAL
;
531 case AV_CH_LAYOUT_6POINT1
:
532 return CHANNEL_LAYOUT_6_1
;
533 case AV_CH_LAYOUT_6POINT1_BACK
:
534 return CHANNEL_LAYOUT_6_1_BACK
;
535 case AV_CH_LAYOUT_6POINT1_FRONT
:
536 return CHANNEL_LAYOUT_6_1_FRONT
;
537 case AV_CH_LAYOUT_7POINT0_FRONT
:
538 return CHANNEL_LAYOUT_7_0_FRONT
;
539 #ifdef AV_CH_LAYOUT_7POINT1_WIDE_BACK
540 case AV_CH_LAYOUT_7POINT1_WIDE_BACK
:
541 return CHANNEL_LAYOUT_7_1_WIDE_BACK
;
543 case AV_CH_LAYOUT_OCTAGONAL
:
544 return CHANNEL_LAYOUT_OCTAGONAL
;
546 // FFmpeg channel_layout is 0 for .wav and .mp3. Attempt to guess layout
547 // based on the channel count.
548 return GuessChannelLayout(channels
);
552 VideoPixelFormat
AVPixelFormatToVideoPixelFormat(AVPixelFormat pixel_format
) {
553 // The YUVJ alternatives are FFmpeg's (deprecated, but still in use) way to
554 // specify a pixel format and full range color combination.
555 switch (pixel_format
) {
556 case AV_PIX_FMT_YUV422P
:
557 case AV_PIX_FMT_YUVJ422P
:
558 return PIXEL_FORMAT_YV16
;
559 case AV_PIX_FMT_YUV444P
:
560 case AV_PIX_FMT_YUVJ444P
:
561 return PIXEL_FORMAT_YV24
;
562 case AV_PIX_FMT_YUV420P
:
563 case AV_PIX_FMT_YUVJ420P
:
564 return PIXEL_FORMAT_YV12
;
565 case AV_PIX_FMT_YUVA420P
:
566 return PIXEL_FORMAT_YV12A
;
568 DVLOG(1) << "Unsupported AVPixelFormat: " << pixel_format
;
570 return PIXEL_FORMAT_UNKNOWN
;
573 AVPixelFormat
VideoPixelFormatToAVPixelFormat(VideoPixelFormat video_format
) {
574 switch (video_format
) {
575 case PIXEL_FORMAT_YV16
:
576 return AV_PIX_FMT_YUV422P
;
577 case PIXEL_FORMAT_YV12
:
578 return AV_PIX_FMT_YUV420P
;
579 case PIXEL_FORMAT_YV12A
:
580 return AV_PIX_FMT_YUVA420P
;
581 case PIXEL_FORMAT_YV24
:
582 return AV_PIX_FMT_YUV444P
;
584 DVLOG(1) << "Unsupported Format: " << video_format
;
586 return AV_PIX_FMT_NONE
;
589 ColorSpace
AVColorSpaceToColorSpace(AVColorSpace color_space
,
590 AVColorRange color_range
) {
591 if (color_range
== AVCOL_RANGE_JPEG
)
592 return COLOR_SPACE_JPEG
;
594 switch (color_space
) {
595 case AVCOL_SPC_UNSPECIFIED
:
597 case AVCOL_SPC_BT709
:
598 return COLOR_SPACE_HD_REC709
;
599 case AVCOL_SPC_SMPTE170M
:
600 case AVCOL_SPC_BT470BG
:
601 return COLOR_SPACE_SD_REC601
;
603 DVLOG(1) << "Unknown AVColorSpace: " << color_space
;
605 return COLOR_SPACE_UNSPECIFIED
;
608 bool FFmpegUTCDateToTime(const char* date_utc
, base::Time
* out
) {
612 std::vector
<base::StringPiece
> fields
= base::SplitStringPiece(
613 date_utc
, " ", base::KEEP_WHITESPACE
, base::SPLIT_WANT_NONEMPTY
);
614 if (fields
.size() != 2)
617 std::vector
<base::StringPiece
> date_fields
= base::SplitStringPiece(
618 fields
[0], "-", base::KEEP_WHITESPACE
, base::SPLIT_WANT_NONEMPTY
);
619 if (date_fields
.size() != 3)
622 // TODO(acolwell): Update this parsing code when FFmpeg returns sub-second
624 std::vector
<base::StringPiece
> time_fields
= base::SplitStringPiece(
625 fields
[1], ":", base::KEEP_WHITESPACE
, base::SPLIT_WANT_NONEMPTY
);
626 if (time_fields
.size() != 3)
629 base::Time::Exploded exploded
;
630 exploded
.millisecond
= 0;
631 if (base::StringToInt(date_fields
[0], &exploded
.year
) &&
632 base::StringToInt(date_fields
[1], &exploded
.month
) &&
633 base::StringToInt(date_fields
[2], &exploded
.day_of_month
) &&
634 base::StringToInt(time_fields
[0], &exploded
.hour
) &&
635 base::StringToInt(time_fields
[1], &exploded
.minute
) &&
636 base::StringToInt(time_fields
[2], &exploded
.second
)) {
637 base::Time parsed_time
= base::Time::FromUTCExploded(exploded
);
638 if (parsed_time
.is_null())