summaryrefslogtreecommitdiff
path: root/chromium/media/filters/ffmpeg_demuxer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/filters/ffmpeg_demuxer.cc')
-rw-r--r--chromium/media/filters/ffmpeg_demuxer.cc114
1 files changed, 80 insertions, 34 deletions
diff --git a/chromium/media/filters/ffmpeg_demuxer.cc b/chromium/media/filters/ffmpeg_demuxer.cc
index 155e98079af..c06dd295de9 100644
--- a/chromium/media/filters/ffmpeg_demuxer.cc
+++ b/chromium/media/filters/ffmpeg_demuxer.cc
@@ -172,14 +172,58 @@ static int32_t GetCodecHash(const AVCodecContext* context) {
return HashCodecName("none");
}
+scoped_ptr<FFmpegDemuxerStream> FFmpegDemuxerStream::Create(
+ FFmpegDemuxer* demuxer,
+ AVStream* stream) {
+ if (!demuxer || !stream)
+ return nullptr;
+
+ scoped_ptr<FFmpegDemuxerStream> demuxer_stream;
+ scoped_ptr<AudioDecoderConfig> audio_config;
+ scoped_ptr<VideoDecoderConfig> video_config;
+
+ if (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+ audio_config.reset(new AudioDecoderConfig());
+
+ // IsValidConfig() checks that the codec is supported and that the channel
+ // layout and sample format are valid.
+ //
+ // TODO(chcunningham): Change AVStreamToAudioDecoderConfig to check
+ // IsValidConfig internally and return a null scoped_ptr if not valid.
+ if (!AVStreamToAudioDecoderConfig(stream, audio_config.get()) ||
+ !audio_config->IsValidConfig())
+ return nullptr;
+
+ } else if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+ video_config.reset(new VideoDecoderConfig());
+
+ // IsValidConfig() checks that the codec is supported and that the channel
+ // layout and sample format are valid.
+ //
+ // TODO(chcunningham): Change AVStreamToVideoDecoderConfig to check
+ // IsValidConfig internally and return a null scoped_ptr if not valid.
+ if (!AVStreamToVideoDecoderConfig(stream, video_config.get()) ||
+ !video_config->IsValidConfig())
+ return nullptr;
+ }
+
+ return make_scoped_ptr(new FFmpegDemuxerStream(
+ demuxer, stream, audio_config.Pass(), video_config.Pass()));
+}
+
//
// FFmpegDemuxerStream
//
-FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer,
- AVStream* stream)
+FFmpegDemuxerStream::FFmpegDemuxerStream(
+ FFmpegDemuxer* demuxer,
+ AVStream* stream,
+ scoped_ptr<AudioDecoderConfig> audio_config,
+ scoped_ptr<VideoDecoderConfig> video_config)
: demuxer_(demuxer),
task_runner_(base::ThreadTaskRunnerHandle::Get()),
stream_(stream),
+ audio_config_(audio_config.release()),
+ video_config_(video_config.release()),
type_(UNKNOWN),
liveness_(LIVENESS_UNKNOWN),
end_of_stream_(false),
@@ -196,14 +240,14 @@ FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer,
// Determine our media format.
switch (stream->codec->codec_type) {
case AVMEDIA_TYPE_AUDIO:
+ DCHECK(audio_config_.get() && !video_config_.get());
type_ = AUDIO;
- AVStreamToAudioDecoderConfig(stream, &audio_config_);
- is_encrypted = audio_config_.is_encrypted();
+ is_encrypted = audio_config_->is_encrypted();
break;
case AVMEDIA_TYPE_VIDEO:
+ DCHECK(video_config_.get() && !audio_config_.get());
type_ = VIDEO;
- AVStreamToVideoDecoderConfig(stream, &video_config_);
- is_encrypted = video_config_.is_encrypted();
+ is_encrypted = video_config_->is_encrypted();
rotation_entry = av_dict_get(stream->metadata, "rotate", NULL, 0);
if (rotation_entry && rotation_entry->value && rotation_entry->value[0])
@@ -228,6 +272,7 @@ FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer,
break;
case AVMEDIA_TYPE_SUBTITLE:
+ DCHECK(!video_config_.get() && !audio_config_.get());
type_ = TEXT;
break;
default:
@@ -315,8 +360,8 @@ void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) {
scoped_ptr<DecryptConfig> decrypt_config;
int data_offset = 0;
- if ((type() == DemuxerStream::AUDIO && audio_config_.is_encrypted()) ||
- (type() == DemuxerStream::VIDEO && video_config_.is_encrypted())) {
+ if ((type() == DemuxerStream::AUDIO && audio_config_->is_encrypted()) ||
+ (type() == DemuxerStream::VIDEO && video_config_->is_encrypted())) {
if (!WebMCreateDecryptConfig(
packet->data, packet->size,
reinterpret_cast<const uint8*>(encryption_key_id_.data()),
@@ -580,14 +625,16 @@ bool FFmpegDemuxerStream::SupportsConfigChanges() { return false; }
AudioDecoderConfig FFmpegDemuxerStream::audio_decoder_config() {
DCHECK(task_runner_->BelongsToCurrentThread());
- CHECK_EQ(type_, AUDIO);
- return audio_config_;
+ DCHECK_EQ(type_, AUDIO);
+ DCHECK(audio_config_.get());
+ return *audio_config_;
}
VideoDecoderConfig FFmpegDemuxerStream::video_decoder_config() {
DCHECK(task_runner_->BelongsToCurrentThread());
- CHECK_EQ(type_, VIDEO);
- return video_config_;
+ DCHECK_EQ(type_, VIDEO);
+ DCHECK(video_config_.get());
+ return *video_config_;
}
VideoRotation FFmpegDemuxerStream::video_rotation() {
@@ -987,7 +1034,6 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
AVStream* audio_stream = NULL;
AudioDecoderConfig audio_config;
-
AVStream* video_stream = NULL;
VideoDecoderConfig video_config;
@@ -1007,13 +1053,6 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
// Log the codec detected, whether it is supported or not.
UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedAudioCodecHash",
GetCodecHash(codec_context));
-
- // Ensure the codec is supported. IsValidConfig() also checks that the
- // channel layout and sample format are valid.
- AVStreamToAudioDecoderConfig(stream, &audio_config);
- if (!audio_config.IsValidConfig())
- continue;
- audio_stream = stream;
} else if (codec_type == AVMEDIA_TYPE_VIDEO) {
if (video_stream)
continue;
@@ -1042,14 +1081,6 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
// Log the codec detected, whether it is supported or not.
UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedVideoCodecHash",
GetCodecHash(codec_context));
-
- // Ensure the codec is supported. IsValidConfig() also checks that the
- // frame size and visible size are valid.
- AVStreamToVideoDecoderConfig(stream, &video_config);
-
- if (!video_config.IsValidConfig())
- continue;
- video_stream = stream;
} else if (codec_type == AVMEDIA_TYPE_SUBTITLE) {
if (codec_context->codec_id != AV_CODEC_ID_WEBVTT || !text_enabled_) {
continue;
@@ -1058,15 +1089,30 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
continue;
}
- streams_[i] = new FFmpegDemuxerStream(this, stream);
+ // Attempt to create a FFmpegDemuxerStream from the AVStream. This will
+ // return nullptr if the AVStream is invalid. Validity checks will verify
+ // things like: codec, channel layout, sample/pixel format, etc...
+ scoped_ptr<FFmpegDemuxerStream> demuxer_stream =
+ FFmpegDemuxerStream::Create(this, stream);
+ if (demuxer_stream.get()) {
+ streams_[i] = demuxer_stream.release();
+ } else {
+ // This AVStream does not successfully convert.
+ continue;
+ }
- // Record audio or video src= playback UMA stats for the stream's decoder
- // config.
+ // Note when we find our audio/video stream (we only want one of each) and
+ // record src= playback UMA stats for the stream's decoder config.
if (codec_type == AVMEDIA_TYPE_AUDIO) {
- RecordAudioCodecStats(streams_[i]->audio_decoder_config());
+ CHECK(!audio_stream);
+ audio_stream = stream;
+ audio_config = streams_[i]->audio_decoder_config();
+ RecordAudioCodecStats(audio_config);
} else if (codec_type == AVMEDIA_TYPE_VIDEO) {
- RecordVideoCodecStats(streams_[i]->video_decoder_config(),
- stream->codec->color_range);
+ CHECK(!video_stream);
+ video_stream = stream;
+ video_config = streams_[i]->video_decoder_config();
+ RecordVideoCodecStats(video_config, stream->codec->color_range);
}
max_duration = std::max(max_duration, streams_[i]->duration());