summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/ffmpeg/ffmpeg_common.cc23
-rw-r--r--media/ffmpeg/ffmpeg_common.h12
-rw-r--r--media/filters/ffmpeg_demuxer.cc27
3 files changed, 36 insertions, 26 deletions
diff --git a/media/ffmpeg/ffmpeg_common.cc b/media/ffmpeg/ffmpeg_common.cc
index e47b8f3..51b4fa9 100644
--- a/media/ffmpeg/ffmpeg_common.cc
+++ b/media/ffmpeg/ffmpeg_common.cc
@@ -57,7 +57,8 @@ int64 ConvertToTimeBase(const AVRational& time_base,
return av_rescale_q(timestamp.InMicroseconds(), kMicrosBase, time_base);
}
-AudioCodec CodecIDToAudioCodec(AVCodecID codec_id) {
+// Converts an FFmpeg audio codec ID into its corresponding supported codec id.
+static AudioCodec CodecIDToAudioCodec(AVCodecID codec_id) {
switch (codec_id) {
case AV_CODEC_ID_AAC:
return kCodecAAC;
@@ -137,7 +138,8 @@ static AVCodecID AudioCodecToCodecID(AudioCodec audio_codec,
return AV_CODEC_ID_NONE;
}
-VideoCodec CodecIDToVideoCodec(AVCodecID codec_id) {
+// Converts an FFmpeg video codec ID into its corresponding supported codec id.
+static VideoCodec CodecIDToVideoCodec(AVCodecID codec_id) {
switch (codec_id) {
case AV_CODEC_ID_H264:
return kCodecH264;
@@ -264,7 +266,8 @@ static AVSampleFormat SampleFormatToAVSampleFormat(SampleFormat sample_format) {
static void AVCodecContextToAudioDecoderConfig(
const AVCodecContext* codec_context,
bool is_encrypted,
- AudioDecoderConfig* config) {
+ AudioDecoderConfig* config,
+ bool record_stats) {
DCHECK_EQ(codec_context->codec_type, AVMEDIA_TYPE_AUDIO);
AudioCodec codec = CodecIDToAudioCodec(codec_context->codec_id);
@@ -288,7 +291,7 @@ static void AVCodecContextToAudioDecoderConfig(
codec_context->extradata,
codec_context->extradata_size,
is_encrypted,
- true);
+ record_stats);
if (codec != kCodecOpus) {
DCHECK_EQ(av_get_bytes_per_sample(codec_context->sample_fmt) * 8,
config->bits_per_channel());
@@ -297,13 +300,14 @@ static void AVCodecContextToAudioDecoderConfig(
void AVStreamToAudioDecoderConfig(
const AVStream* stream,
- AudioDecoderConfig* config) {
+ AudioDecoderConfig* config,
+ bool record_stats) {
bool is_encrypted = false;
AVDictionaryEntry* key = av_dict_get(stream->metadata, "enc_key_id", NULL, 0);
if (key)
is_encrypted = true;
- return AVCodecContextToAudioDecoderConfig(stream->codec,
- is_encrypted, config);
+ return AVCodecContextToAudioDecoderConfig(
+ stream->codec, is_encrypted, config, record_stats);
}
void AudioDecoderConfigToAVCodecContext(const AudioDecoderConfig& config,
@@ -336,7 +340,8 @@ void AudioDecoderConfigToAVCodecContext(const AudioDecoderConfig& config,
void AVStreamToVideoDecoderConfig(
const AVStream* stream,
- VideoDecoderConfig* config) {
+ VideoDecoderConfig* config,
+ bool record_stats) {
gfx::Size coded_size(stream->codec->coded_width, stream->codec->coded_height);
// TODO(vrk): This assumes decoded frame data starts at (0, 0), which is true
@@ -386,7 +391,7 @@ void AVStreamToVideoDecoderConfig(
coded_size, visible_rect, natural_size,
stream->codec->extradata, stream->codec->extradata_size,
is_encrypted,
- true);
+ record_stats);
}
void VideoDecoderConfigToAVCodecContext(
diff --git a/media/ffmpeg/ffmpeg_common.h b/media/ffmpeg/ffmpeg_common.h
index 6cb7862..cc5955c 100644
--- a/media/ffmpeg/ffmpeg_common.h
+++ b/media/ffmpeg/ffmpeg_common.h
@@ -74,14 +74,16 @@ MEDIA_EXPORT int64 ConvertToTimeBase(const AVRational& time_base,
void AVStreamToAudioDecoderConfig(
const AVStream* stream,
- AudioDecoderConfig* config);
+ AudioDecoderConfig* config,
+ bool record_stats);
void AudioDecoderConfigToAVCodecContext(
const AudioDecoderConfig& config,
AVCodecContext* codec_context);
void AVStreamToVideoDecoderConfig(
const AVStream* stream,
- VideoDecoderConfig* config);
+ VideoDecoderConfig* config,
+ bool record_stats);
void VideoDecoderConfigToAVCodecContext(
const VideoDecoderConfig& config,
AVCodecContext* codec_context);
@@ -98,12 +100,6 @@ VideoFrame::Format PixelFormatToVideoFormat(PixelFormat pixel_format);
// Converts video formats to its corresponding FFmpeg's pixel formats.
PixelFormat VideoFormatToPixelFormat(VideoFrame::Format video_format);
-// Converts an FFmpeg video codec ID into its corresponding supported codec id.
-VideoCodec CodecIDToVideoCodec(AVCodecID codec_id);
-
-// Converts an FFmpeg audio codec ID into its corresponding supported codec id.
-AudioCodec CodecIDToAudioCodec(AVCodecID codec_id);
-
} // namespace media
#endif // MEDIA_FFMPEG_FFMPEG_COMMON_H_
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index a168c24..ff93595 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -54,12 +54,12 @@ FFmpegDemuxerStream::FFmpegDemuxerStream(
switch (stream->codec->codec_type) {
case AVMEDIA_TYPE_AUDIO:
type_ = AUDIO;
- AVStreamToAudioDecoderConfig(stream, &audio_config_);
+ AVStreamToAudioDecoderConfig(stream, &audio_config_, true);
is_encrypted = audio_config_.is_encrypted();
break;
case AVMEDIA_TYPE_VIDEO:
type_ = VIDEO;
- AVStreamToVideoDecoderConfig(stream, &video_config_);
+ AVStreamToVideoDecoderConfig(stream, &video_config_, true);
is_encrypted = video_config_.is_encrypted();
break;
default:
@@ -475,7 +475,10 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
return;
}
- // Create demuxer stream entries for each possible AVStream.
+ // Create demuxer stream entries for each possible AVStream. Each stream
+ // is examined to determine if it is supported or not (is the codec enabled
+ // for it in this release?). Unsupported streams are skipped, allowing for
+ // partial playback. At least one audio or video stream must be playable.
AVFormatContext* format_context = glue_->format_context();
streams_.resize(format_context->nb_streams);
bool found_audio_stream = false;
@@ -483,7 +486,8 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
base::TimeDelta max_duration;
for (size_t i = 0; i < format_context->nb_streams; ++i) {
- AVCodecContext* codec_context = format_context->streams[i]->codec;
+ AVStream* stream = format_context->streams[i];
+ AVCodecContext* codec_context = stream->codec;
AVMediaType codec_type = codec_context->codec_type;
if (codec_type == AVMEDIA_TYPE_AUDIO) {
@@ -492,8 +496,11 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
// Log the codec detected, whether it is supported or not.
UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedAudioCodec",
codec_context->codec_id);
- // Ensure the codec is supported.
- if (CodecIDToAudioCodec(codec_context->codec_id) == kUnknownAudioCodec)
+ // Ensure the codec is supported. IsValidConfig() also checks that the
+ // channel layout and sample format are valid.
+ AudioDecoderConfig audio_config;
+ AVStreamToAudioDecoderConfig(stream, &audio_config, false);
+ if (!audio_config.IsValidConfig())
continue;
found_audio_stream = true;
} else if (codec_type == AVMEDIA_TYPE_VIDEO) {
@@ -502,15 +509,17 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
// Log the codec detected, whether it is supported or not.
UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedVideoCodec",
codec_context->codec_id);
- // Ensure the codec is supported.
- if (CodecIDToVideoCodec(codec_context->codec_id) == kUnknownVideoCodec)
+ // Ensure the codec is supported. IsValidConfig() also checks that the
+ // frame size and visible size are valid.
+ VideoDecoderConfig video_config;
+ AVStreamToVideoDecoderConfig(stream, &video_config, false);
+ if (!video_config.IsValidConfig())
continue;
found_video_stream = true;
} else {
continue;
}
- AVStream* stream = format_context->streams[i];
streams_[i] = new FFmpegDemuxerStream(this, stream);
max_duration = std::max(max_duration, streams_[i]->duration());