• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "media/ffmpeg/ffmpeg_common.h"
6 
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_util.h"
12 #include "media/base/decoder_buffer.h"
13 #include "media/base/video_frame.h"
14 #include "media/base/video_util.h"
15 
16 namespace media {
17 
18 // Why FF_INPUT_BUFFER_PADDING_SIZE? FFmpeg assumes all input buffers are
19 // padded. Check here to ensure FFmpeg only receives data padded to its
20 // specifications.
21 COMPILE_ASSERT(DecoderBuffer::kPaddingSize >= FF_INPUT_BUFFER_PADDING_SIZE,
22                decoder_buffer_padding_size_does_not_fit_ffmpeg_requirement);
23 
24 // Alignment requirement by FFmpeg for input and output buffers. This need to
25 // be updated to match FFmpeg when it changes.
26 #if defined(ARCH_CPU_ARM_FAMILY)
27 static const int kFFmpegBufferAddressAlignment = 16;
28 #else
29 static const int kFFmpegBufferAddressAlignment = 32;
30 #endif
31 
32 // Check here to ensure FFmpeg only receives data aligned to its specifications.
33 COMPILE_ASSERT(
34     DecoderBuffer::kAlignmentSize >= kFFmpegBufferAddressAlignment &&
35     DecoderBuffer::kAlignmentSize % kFFmpegBufferAddressAlignment == 0,
36     decoder_buffer_alignment_size_does_not_fit_ffmpeg_requirement);
37 
38 // Allows faster SIMD YUV convert. Also, FFmpeg overreads/-writes occasionally.
39 // See video_get_buffer() in libavcodec/utils.c.
40 static const int kFFmpegOutputBufferPaddingSize = 16;
41 
42 COMPILE_ASSERT(VideoFrame::kFrameSizePadding >= kFFmpegOutputBufferPaddingSize,
43                video_frame_padding_size_does_not_fit_ffmpeg_requirement);
44 
45 COMPILE_ASSERT(
46     VideoFrame::kFrameAddressAlignment >= kFFmpegBufferAddressAlignment &&
47     VideoFrame::kFrameAddressAlignment % kFFmpegBufferAddressAlignment == 0,
48     video_frame_address_alignment_does_not_fit_ffmpeg_requirement);
49 
50 static const AVRational kMicrosBase = { 1, base::Time::kMicrosecondsPerSecond };
51 
ConvertFromTimeBase(const AVRational & time_base,int64 timestamp)52 base::TimeDelta ConvertFromTimeBase(const AVRational& time_base,
53                                     int64 timestamp) {
54   int64 microseconds = av_rescale_q(timestamp, time_base, kMicrosBase);
55   return base::TimeDelta::FromMicroseconds(microseconds);
56 }
57 
ConvertToTimeBase(const AVRational & time_base,const base::TimeDelta & timestamp)58 int64 ConvertToTimeBase(const AVRational& time_base,
59                         const base::TimeDelta& timestamp) {
60   return av_rescale_q(timestamp.InMicroseconds(), kMicrosBase, time_base);
61 }
62 
63 // Converts an FFmpeg audio codec ID into its corresponding supported codec id.
CodecIDToAudioCodec(AVCodecID codec_id)64 static AudioCodec CodecIDToAudioCodec(AVCodecID codec_id) {
65   switch (codec_id) {
66     case AV_CODEC_ID_AAC:
67       return kCodecAAC;
68     case AV_CODEC_ID_MP3:
69       return kCodecMP3;
70     case AV_CODEC_ID_VORBIS:
71       return kCodecVorbis;
72     case AV_CODEC_ID_PCM_U8:
73     case AV_CODEC_ID_PCM_S16LE:
74     case AV_CODEC_ID_PCM_S24LE:
75     case AV_CODEC_ID_PCM_F32LE:
76       return kCodecPCM;
77     case AV_CODEC_ID_PCM_S16BE:
78       return kCodecPCM_S16BE;
79     case AV_CODEC_ID_PCM_S24BE:
80       return kCodecPCM_S24BE;
81     case AV_CODEC_ID_FLAC:
82       return kCodecFLAC;
83     case AV_CODEC_ID_AMR_NB:
84       return kCodecAMR_NB;
85     case AV_CODEC_ID_AMR_WB:
86       return kCodecAMR_WB;
87     case AV_CODEC_ID_GSM_MS:
88       return kCodecGSM_MS;
89     case AV_CODEC_ID_PCM_ALAW:
90       return kCodecPCM_ALAW;
91     case AV_CODEC_ID_PCM_MULAW:
92       return kCodecPCM_MULAW;
93     case AV_CODEC_ID_OPUS:
94       return kCodecOpus;
95     default:
96       DVLOG(1) << "Unknown audio CodecID: " << codec_id;
97   }
98   return kUnknownAudioCodec;
99 }
100 
AudioCodecToCodecID(AudioCodec audio_codec,SampleFormat sample_format)101 static AVCodecID AudioCodecToCodecID(AudioCodec audio_codec,
102                                      SampleFormat sample_format) {
103   switch (audio_codec) {
104     case kCodecAAC:
105       return AV_CODEC_ID_AAC;
106     case kCodecMP3:
107       return AV_CODEC_ID_MP3;
108     case kCodecPCM:
109       switch (sample_format) {
110         case kSampleFormatU8:
111           return AV_CODEC_ID_PCM_U8;
112         case kSampleFormatS16:
113           return AV_CODEC_ID_PCM_S16LE;
114         case kSampleFormatS32:
115           return AV_CODEC_ID_PCM_S24LE;
116         case kSampleFormatF32:
117           return AV_CODEC_ID_PCM_F32LE;
118         default:
119           DVLOG(1) << "Unsupported sample format: " << sample_format;
120       }
121       break;
122     case kCodecPCM_S16BE:
123       return AV_CODEC_ID_PCM_S16BE;
124     case kCodecPCM_S24BE:
125       return AV_CODEC_ID_PCM_S24BE;
126     case kCodecVorbis:
127       return AV_CODEC_ID_VORBIS;
128     case kCodecFLAC:
129       return AV_CODEC_ID_FLAC;
130     case kCodecAMR_NB:
131       return AV_CODEC_ID_AMR_NB;
132     case kCodecAMR_WB:
133       return AV_CODEC_ID_AMR_WB;
134     case kCodecGSM_MS:
135       return AV_CODEC_ID_GSM_MS;
136     case kCodecPCM_ALAW:
137       return AV_CODEC_ID_PCM_ALAW;
138     case kCodecPCM_MULAW:
139       return AV_CODEC_ID_PCM_MULAW;
140     case kCodecOpus:
141       return AV_CODEC_ID_OPUS;
142     default:
143       DVLOG(1) << "Unknown AudioCodec: " << audio_codec;
144   }
145   return AV_CODEC_ID_NONE;
146 }
147 
148 // Converts an FFmpeg video codec ID into its corresponding supported codec id.
CodecIDToVideoCodec(AVCodecID codec_id)149 static VideoCodec CodecIDToVideoCodec(AVCodecID codec_id) {
150   switch (codec_id) {
151     case AV_CODEC_ID_H264:
152       return kCodecH264;
153     case AV_CODEC_ID_THEORA:
154       return kCodecTheora;
155     case AV_CODEC_ID_MPEG4:
156       return kCodecMPEG4;
157     case AV_CODEC_ID_VP8:
158       return kCodecVP8;
159     case AV_CODEC_ID_VP9:
160       return kCodecVP9;
161     default:
162       DVLOG(1) << "Unknown video CodecID: " << codec_id;
163   }
164   return kUnknownVideoCodec;
165 }
166 
VideoCodecToCodecID(VideoCodec video_codec)167 static AVCodecID VideoCodecToCodecID(VideoCodec video_codec) {
168   switch (video_codec) {
169     case kCodecH264:
170       return AV_CODEC_ID_H264;
171     case kCodecTheora:
172       return AV_CODEC_ID_THEORA;
173     case kCodecMPEG4:
174       return AV_CODEC_ID_MPEG4;
175     case kCodecVP8:
176       return AV_CODEC_ID_VP8;
177     case kCodecVP9:
178       return AV_CODEC_ID_VP9;
179     default:
180       DVLOG(1) << "Unknown VideoCodec: " << video_codec;
181   }
182   return AV_CODEC_ID_NONE;
183 }
184 
ProfileIDToVideoCodecProfile(int profile)185 static VideoCodecProfile ProfileIDToVideoCodecProfile(int profile) {
186   // Clear out the CONSTRAINED & INTRA flags which are strict subsets of the
187   // corresponding profiles with which they're used.
188   profile &= ~FF_PROFILE_H264_CONSTRAINED;
189   profile &= ~FF_PROFILE_H264_INTRA;
190   switch (profile) {
191     case FF_PROFILE_H264_BASELINE:
192       return H264PROFILE_BASELINE;
193     case FF_PROFILE_H264_MAIN:
194       return H264PROFILE_MAIN;
195     case FF_PROFILE_H264_EXTENDED:
196       return H264PROFILE_EXTENDED;
197     case FF_PROFILE_H264_HIGH:
198       return H264PROFILE_HIGH;
199     case FF_PROFILE_H264_HIGH_10:
200       return H264PROFILE_HIGH10PROFILE;
201     case FF_PROFILE_H264_HIGH_422:
202       return H264PROFILE_HIGH422PROFILE;
203     case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
204       return H264PROFILE_HIGH444PREDICTIVEPROFILE;
205     default:
206       DVLOG(1) << "Unknown profile id: " << profile;
207   }
208   return VIDEO_CODEC_PROFILE_UNKNOWN;
209 }
210 
VideoCodecProfileToProfileID(VideoCodecProfile profile)211 static int VideoCodecProfileToProfileID(VideoCodecProfile profile) {
212   switch (profile) {
213     case H264PROFILE_BASELINE:
214       return FF_PROFILE_H264_BASELINE;
215     case H264PROFILE_MAIN:
216       return FF_PROFILE_H264_MAIN;
217     case H264PROFILE_EXTENDED:
218       return FF_PROFILE_H264_EXTENDED;
219     case H264PROFILE_HIGH:
220       return FF_PROFILE_H264_HIGH;
221     case H264PROFILE_HIGH10PROFILE:
222       return FF_PROFILE_H264_HIGH_10;
223     case H264PROFILE_HIGH422PROFILE:
224       return FF_PROFILE_H264_HIGH_422;
225     case H264PROFILE_HIGH444PREDICTIVEPROFILE:
226       return FF_PROFILE_H264_HIGH_444_PREDICTIVE;
227     default:
228       DVLOG(1) << "Unknown VideoCodecProfile: " << profile;
229   }
230   return FF_PROFILE_UNKNOWN;
231 }
232 
AVSampleFormatToSampleFormat(AVSampleFormat sample_format)233 SampleFormat AVSampleFormatToSampleFormat(AVSampleFormat sample_format) {
234   switch (sample_format) {
235     case AV_SAMPLE_FMT_U8:
236       return kSampleFormatU8;
237     case AV_SAMPLE_FMT_S16:
238       return kSampleFormatS16;
239     case AV_SAMPLE_FMT_S32:
240       return kSampleFormatS32;
241     case AV_SAMPLE_FMT_FLT:
242       return kSampleFormatF32;
243     case AV_SAMPLE_FMT_S16P:
244       return kSampleFormatPlanarS16;
245     case AV_SAMPLE_FMT_FLTP:
246       return kSampleFormatPlanarF32;
247     default:
248       DVLOG(1) << "Unknown AVSampleFormat: " << sample_format;
249   }
250   return kUnknownSampleFormat;
251 }
252 
SampleFormatToAVSampleFormat(SampleFormat sample_format)253 static AVSampleFormat SampleFormatToAVSampleFormat(SampleFormat sample_format) {
254   switch (sample_format) {
255     case kSampleFormatU8:
256       return AV_SAMPLE_FMT_U8;
257     case kSampleFormatS16:
258       return AV_SAMPLE_FMT_S16;
259     case kSampleFormatS32:
260       return AV_SAMPLE_FMT_S32;
261     case kSampleFormatF32:
262       return AV_SAMPLE_FMT_FLT;
263     case kSampleFormatPlanarS16:
264       return AV_SAMPLE_FMT_S16P;
265     case kSampleFormatPlanarF32:
266       return AV_SAMPLE_FMT_FLTP;
267     default:
268       DVLOG(1) << "Unknown SampleFormat: " << sample_format;
269   }
270   return AV_SAMPLE_FMT_NONE;
271 }
272 
AVCodecContextToAudioDecoderConfig(const AVCodecContext * codec_context,bool is_encrypted,AudioDecoderConfig * config,bool record_stats)273 void AVCodecContextToAudioDecoderConfig(
274     const AVCodecContext* codec_context,
275     bool is_encrypted,
276     AudioDecoderConfig* config,
277     bool record_stats) {
278   DCHECK_EQ(codec_context->codec_type, AVMEDIA_TYPE_AUDIO);
279 
280   AudioCodec codec = CodecIDToAudioCodec(codec_context->codec_id);
281 
282   SampleFormat sample_format =
283       AVSampleFormatToSampleFormat(codec_context->sample_fmt);
284 
285   ChannelLayout channel_layout = ChannelLayoutToChromeChannelLayout(
286       codec_context->channel_layout, codec_context->channels);
287 
288   int sample_rate = codec_context->sample_rate;
289   if (codec == kCodecOpus) {
290     // |codec_context->sample_fmt| is not set by FFmpeg because Opus decoding is
291     // not enabled in FFmpeg.  It doesn't matter what value is set here, so long
292     // as it's valid, the true sample format is selected inside the decoder.
293     sample_format = kSampleFormatF32;
294 
295     // Always use 48kHz for OPUS.  Technically we should match to the highest
296     // supported hardware sample rate among [8, 12, 16, 24, 48] kHz, but we
297     // don't know the hardware sample rate at this point and those rates are
298     // rarely used for output.  See the "Input Sample Rate" section of the spec:
299     // http://tools.ietf.org/html/draft-terriberry-oggopus-01#page-11
300     sample_rate = 48000;
301   }
302 
303   base::TimeDelta seek_preroll;
304   if (codec_context->seek_preroll > 0) {
305     seek_preroll = base::TimeDelta::FromMicroseconds(
306         codec_context->seek_preroll * 1000000.0 / codec_context->sample_rate);
307   }
308 
309   config->Initialize(codec,
310                      sample_format,
311                      channel_layout,
312                      sample_rate,
313                      codec_context->extradata,
314                      codec_context->extradata_size,
315                      is_encrypted,
316                      record_stats,
317                      seek_preroll,
318                      codec_context->delay);
319   if (codec != kCodecOpus) {
320     DCHECK_EQ(av_get_bytes_per_sample(codec_context->sample_fmt) * 8,
321               config->bits_per_channel());
322   }
323 }
324 
AVStreamToAudioDecoderConfig(const AVStream * stream,AudioDecoderConfig * config,bool record_stats)325 void AVStreamToAudioDecoderConfig(
326     const AVStream* stream,
327     AudioDecoderConfig* config,
328     bool record_stats) {
329   bool is_encrypted = false;
330   AVDictionaryEntry* key = av_dict_get(stream->metadata, "enc_key_id", NULL, 0);
331   if (key)
332     is_encrypted = true;
333   return AVCodecContextToAudioDecoderConfig(
334       stream->codec, is_encrypted, config, record_stats);
335 }
336 
AudioDecoderConfigToAVCodecContext(const AudioDecoderConfig & config,AVCodecContext * codec_context)337 void AudioDecoderConfigToAVCodecContext(const AudioDecoderConfig& config,
338                                         AVCodecContext* codec_context) {
339   codec_context->codec_type = AVMEDIA_TYPE_AUDIO;
340   codec_context->codec_id = AudioCodecToCodecID(config.codec(),
341                                                 config.sample_format());
342   codec_context->sample_fmt = SampleFormatToAVSampleFormat(
343       config.sample_format());
344 
345   // TODO(scherkus): should we set |channel_layout|? I'm not sure if FFmpeg uses
346   // said information to decode.
347   codec_context->channels =
348       ChannelLayoutToChannelCount(config.channel_layout());
349   codec_context->sample_rate = config.samples_per_second();
350 
351   if (config.extra_data()) {
352     codec_context->extradata_size = config.extra_data_size();
353     codec_context->extradata = reinterpret_cast<uint8_t*>(
354         av_malloc(config.extra_data_size() + FF_INPUT_BUFFER_PADDING_SIZE));
355     memcpy(codec_context->extradata, config.extra_data(),
356            config.extra_data_size());
357     memset(codec_context->extradata + config.extra_data_size(), '\0',
358            FF_INPUT_BUFFER_PADDING_SIZE);
359   } else {
360     codec_context->extradata = NULL;
361     codec_context->extradata_size = 0;
362   }
363 }
364 
AVStreamToVideoDecoderConfig(const AVStream * stream,VideoDecoderConfig * config,bool record_stats)365 void AVStreamToVideoDecoderConfig(
366     const AVStream* stream,
367     VideoDecoderConfig* config,
368     bool record_stats) {
369   gfx::Size coded_size(stream->codec->coded_width, stream->codec->coded_height);
370 
371   // TODO(vrk): This assumes decoded frame data starts at (0, 0), which is true
372   // for now, but may not always be true forever. Fix this in the future.
373   gfx::Rect visible_rect(stream->codec->width, stream->codec->height);
374 
375   AVRational aspect_ratio = { 1, 1 };
376   if (stream->sample_aspect_ratio.num)
377     aspect_ratio = stream->sample_aspect_ratio;
378   else if (stream->codec->sample_aspect_ratio.num)
379     aspect_ratio = stream->codec->sample_aspect_ratio;
380 
381   VideoCodec codec = CodecIDToVideoCodec(stream->codec->codec_id);
382 
383   VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN;
384   if (codec == kCodecVP8)
385     profile = VP8PROFILE_ANY;
386   else if (codec == kCodecVP9)
387     profile = VP9PROFILE_ANY;
388   else
389     profile = ProfileIDToVideoCodecProfile(stream->codec->profile);
390 
391   gfx::Size natural_size = GetNaturalSize(
392       visible_rect.size(), aspect_ratio.num, aspect_ratio.den);
393 
394   if (record_stats) {
395     // Note the PRESUBMIT_IGNORE_UMA_MAX below, this silences the PRESUBMIT.py
396     // check for uma enum max usage, since we're abusing
397     // UMA_HISTOGRAM_ENUMERATION to report a discrete value.
398     UMA_HISTOGRAM_ENUMERATION("Media.VideoColorRange",
399                               stream->codec->color_range,
400                               AVCOL_RANGE_NB);  // PRESUBMIT_IGNORE_UMA_MAX
401   }
402 
403   VideoFrame::Format format = PixelFormatToVideoFormat(stream->codec->pix_fmt);
404   if (codec == kCodecVP9) {
405     // TODO(tomfinegan): libavcodec doesn't know about VP9.
406     format = VideoFrame::YV12;
407     coded_size = visible_rect.size();
408   }
409 
410   // Pad out |coded_size| for subsampled YUV formats.
411   if (format != VideoFrame::YV24) {
412     coded_size.set_width((coded_size.width() + 1) / 2 * 2);
413     if (format != VideoFrame::YV16)
414       coded_size.set_height((coded_size.height() + 1) / 2 * 2);
415   }
416 
417   bool is_encrypted = false;
418   AVDictionaryEntry* key = av_dict_get(stream->metadata, "enc_key_id", NULL, 0);
419   if (key)
420     is_encrypted = true;
421 
422   AVDictionaryEntry* webm_alpha =
423       av_dict_get(stream->metadata, "alpha_mode", NULL, 0);
424   if (webm_alpha && !strcmp(webm_alpha->value, "1")) {
425     format = VideoFrame::YV12A;
426   }
427 
428   config->Initialize(codec,
429                      profile,
430                      format,
431                      coded_size, visible_rect, natural_size,
432                      stream->codec->extradata, stream->codec->extradata_size,
433                      is_encrypted,
434                      record_stats);
435 }
436 
VideoDecoderConfigToAVCodecContext(const VideoDecoderConfig & config,AVCodecContext * codec_context)437 void VideoDecoderConfigToAVCodecContext(
438     const VideoDecoderConfig& config,
439     AVCodecContext* codec_context) {
440   codec_context->codec_type = AVMEDIA_TYPE_VIDEO;
441   codec_context->codec_id = VideoCodecToCodecID(config.codec());
442   codec_context->profile = VideoCodecProfileToProfileID(config.profile());
443   codec_context->coded_width = config.coded_size().width();
444   codec_context->coded_height = config.coded_size().height();
445   codec_context->pix_fmt = VideoFormatToPixelFormat(config.format());
446 
447   if (config.extra_data()) {
448     codec_context->extradata_size = config.extra_data_size();
449     codec_context->extradata = reinterpret_cast<uint8_t*>(
450         av_malloc(config.extra_data_size() + FF_INPUT_BUFFER_PADDING_SIZE));
451     memcpy(codec_context->extradata, config.extra_data(),
452            config.extra_data_size());
453     memset(codec_context->extradata + config.extra_data_size(), '\0',
454            FF_INPUT_BUFFER_PADDING_SIZE);
455   } else {
456     codec_context->extradata = NULL;
457     codec_context->extradata_size = 0;
458   }
459 }
460 
ChannelLayoutToChromeChannelLayout(int64_t layout,int channels)461 ChannelLayout ChannelLayoutToChromeChannelLayout(int64_t layout, int channels) {
462   switch (layout) {
463     case AV_CH_LAYOUT_MONO:
464       return CHANNEL_LAYOUT_MONO;
465     case AV_CH_LAYOUT_STEREO:
466       return CHANNEL_LAYOUT_STEREO;
467     case AV_CH_LAYOUT_2_1:
468       return CHANNEL_LAYOUT_2_1;
469     case AV_CH_LAYOUT_SURROUND:
470       return CHANNEL_LAYOUT_SURROUND;
471     case AV_CH_LAYOUT_4POINT0:
472       return CHANNEL_LAYOUT_4_0;
473     case AV_CH_LAYOUT_2_2:
474       return CHANNEL_LAYOUT_2_2;
475     case AV_CH_LAYOUT_QUAD:
476       return CHANNEL_LAYOUT_QUAD;
477     case AV_CH_LAYOUT_5POINT0:
478       return CHANNEL_LAYOUT_5_0;
479     case AV_CH_LAYOUT_5POINT1:
480       return CHANNEL_LAYOUT_5_1;
481     case AV_CH_LAYOUT_5POINT0_BACK:
482       return CHANNEL_LAYOUT_5_0_BACK;
483     case AV_CH_LAYOUT_5POINT1_BACK:
484       return CHANNEL_LAYOUT_5_1_BACK;
485     case AV_CH_LAYOUT_7POINT0:
486       return CHANNEL_LAYOUT_7_0;
487     case AV_CH_LAYOUT_7POINT1:
488       return CHANNEL_LAYOUT_7_1;
489     case AV_CH_LAYOUT_7POINT1_WIDE:
490       return CHANNEL_LAYOUT_7_1_WIDE;
491     case AV_CH_LAYOUT_STEREO_DOWNMIX:
492       return CHANNEL_LAYOUT_STEREO_DOWNMIX;
493     case AV_CH_LAYOUT_2POINT1:
494       return CHANNEL_LAYOUT_2POINT1;
495     case AV_CH_LAYOUT_3POINT1:
496       return CHANNEL_LAYOUT_3_1;
497     case AV_CH_LAYOUT_4POINT1:
498       return CHANNEL_LAYOUT_4_1;
499     case AV_CH_LAYOUT_6POINT0:
500       return CHANNEL_LAYOUT_6_0;
501     case AV_CH_LAYOUT_6POINT0_FRONT:
502       return CHANNEL_LAYOUT_6_0_FRONT;
503     case AV_CH_LAYOUT_HEXAGONAL:
504       return CHANNEL_LAYOUT_HEXAGONAL;
505     case AV_CH_LAYOUT_6POINT1:
506       return CHANNEL_LAYOUT_6_1;
507     case AV_CH_LAYOUT_6POINT1_BACK:
508       return CHANNEL_LAYOUT_6_1_BACK;
509     case AV_CH_LAYOUT_6POINT1_FRONT:
510       return CHANNEL_LAYOUT_6_1_FRONT;
511     case AV_CH_LAYOUT_7POINT0_FRONT:
512       return CHANNEL_LAYOUT_7_0_FRONT;
513 #ifdef AV_CH_LAYOUT_7POINT1_WIDE_BACK
514     case AV_CH_LAYOUT_7POINT1_WIDE_BACK:
515       return CHANNEL_LAYOUT_7_1_WIDE_BACK;
516 #endif
517     case AV_CH_LAYOUT_OCTAGONAL:
518       return CHANNEL_LAYOUT_OCTAGONAL;
519     default:
520       // FFmpeg channel_layout is 0 for .wav and .mp3.  Attempt to guess layout
521       // based on the channel count.
522       return GuessChannelLayout(channels);
523   }
524 }
525 
PixelFormatToVideoFormat(PixelFormat pixel_format)526 VideoFrame::Format PixelFormatToVideoFormat(PixelFormat pixel_format) {
527   switch (pixel_format) {
528     case PIX_FMT_YUV422P:
529       return VideoFrame::YV16;
530     case PIX_FMT_YUV444P:
531       return VideoFrame::YV24;
532     case PIX_FMT_YUV420P:
533       return VideoFrame::YV12;
534     case PIX_FMT_YUVJ420P:
535       return VideoFrame::YV12J;
536     case PIX_FMT_YUVA420P:
537       return VideoFrame::YV12A;
538     default:
539       DVLOG(1) << "Unsupported PixelFormat: " << pixel_format;
540   }
541   return VideoFrame::UNKNOWN;
542 }
543 
VideoFormatToPixelFormat(VideoFrame::Format video_format)544 PixelFormat VideoFormatToPixelFormat(VideoFrame::Format video_format) {
545   switch (video_format) {
546     case VideoFrame::YV16:
547       return PIX_FMT_YUV422P;
548     case VideoFrame::YV12:
549       return PIX_FMT_YUV420P;
550     case VideoFrame::YV12J:
551       return PIX_FMT_YUVJ420P;
552     case VideoFrame::YV12A:
553       return PIX_FMT_YUVA420P;
554     case VideoFrame::YV24:
555       return PIX_FMT_YUV444P;
556     default:
557       DVLOG(1) << "Unsupported VideoFrame::Format: " << video_format;
558   }
559   return PIX_FMT_NONE;
560 }
561 
FFmpegUTCDateToTime(const char * date_utc,base::Time * out)562 bool FFmpegUTCDateToTime(const char* date_utc,
563                          base::Time* out) {
564   DCHECK(date_utc);
565   DCHECK(out);
566 
567   std::vector<std::string> fields;
568   std::vector<std::string> date_fields;
569   std::vector<std::string> time_fields;
570   base::Time::Exploded exploded;
571   exploded.millisecond = 0;
572 
573   // TODO(acolwell): Update this parsing code when FFmpeg returns sub-second
574   // information.
575   if ((Tokenize(date_utc, " ", &fields) == 2) &&
576       (Tokenize(fields[0], "-", &date_fields) == 3) &&
577       (Tokenize(fields[1], ":", &time_fields) == 3) &&
578       base::StringToInt(date_fields[0], &exploded.year) &&
579       base::StringToInt(date_fields[1], &exploded.month) &&
580       base::StringToInt(date_fields[2], &exploded.day_of_month) &&
581       base::StringToInt(time_fields[0], &exploded.hour) &&
582       base::StringToInt(time_fields[1], &exploded.minute) &&
583       base::StringToInt(time_fields[2], &exploded.second)) {
584     base::Time parsed_time = base::Time::FromUTCExploded(exploded);
585     if (parsed_time.is_null())
586       return false;
587 
588     *out = parsed_time;
589     return true;
590   }
591 
592   return false;
593 }
594 
595 }  // namespace media
596