| Index: media/filters/ffmpeg_demuxer.cc
|
| diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
|
| index d13fd71c80fd529835b73d4499defd44f4a4229b..093e4f539b13847a1f7f6beb0e140674af037f69 100644
|
| --- a/media/filters/ffmpeg_demuxer.cc
|
| +++ b/media/filters/ffmpeg_demuxer.cc
|
| @@ -54,8 +54,10 @@ static base::Time ExtractTimelineOffset(AVFormatContext* format_context) {
|
| av_dict_get(format_context->metadata, "creation_time", NULL, 0);
|
|
|
| base::Time timeline_offset;
|
| +
|
| + // FFmpegDemuxerTests assume base::Time::FromUTCString() is used here.
|
| if (entry != NULL && entry->value != NULL &&
|
| - FFmpegUTCDateToTime(entry->value, &timeline_offset)) {
|
| + base::Time::FromUTCString(entry->value, &timeline_offset)) {
|
| return timeline_offset;
|
| }
|
| }
|
| @@ -179,11 +181,8 @@ static void RecordVideoCodecStats(const VideoDecoderConfig& video_config,
|
|
|
| static const char kCodecNone[] = "none";
|
|
|
| -static const char* GetCodecName(const AVCodecContext* context) {
|
| - if (context->codec_descriptor)
|
| - return context->codec_descriptor->name;
|
| - const AVCodecDescriptor* codec_descriptor =
|
| - avcodec_descriptor_get(context->codec_id);
|
| +static const char* GetCodecName(enum AVCodecID id) {
|
| + const AVCodecDescriptor* codec_descriptor = avcodec_descriptor_get(id);
|
| // If the codec name can't be determined, return none for tracking.
|
| return codec_descriptor ? codec_descriptor->name : kCodecNone;
|
| }
|
| @@ -210,7 +209,7 @@ std::unique_ptr<FFmpegDemuxerStream> FFmpegDemuxerStream::Create(
|
| std::unique_ptr<AudioDecoderConfig> audio_config;
|
| std::unique_ptr<VideoDecoderConfig> video_config;
|
|
|
| - if (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
|
| + if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
| audio_config.reset(new AudioDecoderConfig());
|
|
|
| // IsValidConfig() checks that the codec is supported and that the channel
|
| @@ -227,7 +226,7 @@ std::unique_ptr<FFmpegDemuxerStream> FFmpegDemuxerStream::Create(
|
|
|
| MEDIA_LOG(INFO, media_log) << "FFmpegDemuxer: created audio stream, config "
|
| << audio_config->AsHumanReadableString();
|
| - } else if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
|
| + } else if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
| video_config.reset(new VideoDecoderConfig());
|
|
|
| // IsValidConfig() checks that the codec is supported and that the channel
|
| @@ -284,7 +283,7 @@ FFmpegDemuxerStream::FFmpegDemuxerStream(
|
| AVDictionaryEntry* rotation_entry = NULL;
|
|
|
| // Determine our media format.
|
| - switch (stream->codec->codec_type) {
|
| + switch (stream->codecpar->codec_type) {
|
| case AVMEDIA_TYPE_AUDIO:
|
| DCHECK(audio_config_.get() && !video_config_.get());
|
| type_ = AUDIO;
|
| @@ -499,7 +498,7 @@ void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) {
|
| if (fixup_negative_timestamps_ && is_audio &&
|
| stream_timestamp < base::TimeDelta() &&
|
| buffer->duration() != kNoTimestamp) {
|
| - if (!stream_->codec->delay) {
|
| + if (!audio_decoder_config().codec_delay()) {
|
| DCHECK_EQ(buffer->discard_padding().first, base::TimeDelta());
|
|
|
| if (stream_timestamp + buffer->duration() < base::TimeDelta()) {
|
| @@ -664,7 +663,7 @@ void FFmpegDemuxerStream::ResetBitstreamConverter() {
|
|
|
| void FFmpegDemuxerStream::InitBitstreamConverter() {
|
| #if defined(USE_PROPRIETARY_CODECS)
|
| - switch (stream_->codec->codec_id) {
|
| + switch (stream_->codecpar->codec_id) {
|
| case AV_CODEC_ID_H264:
|
| // Clear |extra_data| so that future (fallback) decoders will know that
|
| // conversion is forcibly enabled on this stream.
|
| @@ -676,17 +675,17 @@ void FFmpegDemuxerStream::InitBitstreamConverter() {
|
| if (video_config_)
|
| video_config_->SetExtraData(std::vector<uint8_t>());
|
| bitstream_converter_.reset(
|
| - new FFmpegH264ToAnnexBBitstreamConverter(stream_->codec));
|
| + new FFmpegH264ToAnnexBBitstreamConverter(stream_->codecpar));
|
| break;
|
| #if BUILDFLAG(ENABLE_HEVC_DEMUXING)
|
| case AV_CODEC_ID_HEVC:
|
| bitstream_converter_.reset(
|
| - new FFmpegH265ToAnnexBBitstreamConverter(stream_->codec));
|
| + new FFmpegH265ToAnnexBBitstreamConverter(stream_->codecpar));
|
| break;
|
| #endif
|
| case AV_CODEC_ID_AAC:
|
| bitstream_converter_.reset(
|
| - new FFmpegAACBitstreamConverter(stream_->codec));
|
| + new FFmpegAACBitstreamConverter(stream_->codecpar));
|
| break;
|
| default:
|
| break;
|
| @@ -1111,8 +1110,8 @@ static int CalculateBitrate(AVFormatContext* format_context,
|
| // Then try to sum the bitrates individually per stream.
|
| int bitrate = 0;
|
| for (size_t i = 0; i < format_context->nb_streams; ++i) {
|
| - AVCodecContext* codec_context = format_context->streams[i]->codec;
|
| - bitrate += codec_context->bit_rate;
|
| + AVCodecParameters* codec_parameters = format_context->streams[i]->codecpar;
|
| + bitrate += codec_parameters->bit_rate;
|
| }
|
| if (bitrate > 0)
|
| return bitrate;
|
| @@ -1223,46 +1222,40 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
|
| int detected_text_track_count = 0;
|
| for (size_t i = 0; i < format_context->nb_streams; ++i) {
|
| AVStream* stream = format_context->streams[i];
|
| - const AVCodecContext* codec_context = stream->codec;
|
| - const AVMediaType codec_type = codec_context->codec_type;
|
| + const AVCodecParameters* codec_parameters = stream->codecpar;
|
| + const AVMediaType codec_type = codec_parameters->codec_type;
|
| + const AVCodecID codec_id = codec_parameters->codec_id;
|
|
|
| if (codec_type == AVMEDIA_TYPE_AUDIO) {
|
| // Log the codec detected, whether it is supported or not, and whether or
|
| // not we have already detected a supported codec in another stream.
|
| UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedAudioCodecHash",
|
| - HashCodecName(GetCodecName(codec_context)));
|
| + HashCodecName(GetCodecName(codec_id)));
|
| detected_audio_track_count++;
|
| } else if (codec_type == AVMEDIA_TYPE_VIDEO) {
|
| // Log the codec detected, whether it is supported or not, and whether or
|
| // not we have already detected a supported codec in another stream.
|
| UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedVideoCodecHash",
|
| - HashCodecName(GetCodecName(codec_context)));
|
| + HashCodecName(GetCodecName(codec_id)));
|
| detected_video_track_count++;
|
|
|
| #if BUILDFLAG(ENABLE_HEVC_DEMUXING)
|
| - if (stream->codec->codec_id == AV_CODEC_ID_HEVC) {
|
| + if (codec_id == AV_CODEC_ID_HEVC) {
|
| // If ffmpeg is built without HEVC parser/decoder support, it will be
|
| // able to demux HEVC based solely on container-provided information,
|
| // but unable to get some of the parameters without parsing the stream
|
| // (e.g. coded size needs to be read from SPS, pixel format is typically
|
| // deduced from decoder config in hvcC box). These are not really needed
|
| // when using external decoder (e.g. hardware decoder), so override them
|
| - // here, to make sure this translates into a valid VideoDecoderConfig.
|
| - if (stream->codec->coded_width == 0 &&
|
| - stream->codec->coded_height == 0) {
|
| - DCHECK(stream->codec->width > 0);
|
| - DCHECK(stream->codec->height > 0);
|
| - stream->codec->coded_width = stream->codec->width;
|
| - stream->codec->coded_height = stream->codec->height;
|
| - }
|
| - if (stream->codec->pix_fmt == AV_PIX_FMT_NONE) {
|
| - stream->codec->pix_fmt = AV_PIX_FMT_YUV420P;
|
| - }
|
| + // to make sure this translates into a valid VideoDecoderConfig. Coded
|
| + // size is overridden in AVStreamToVideoDecoderConfig().
|
| + if (stream->codecpar->format == AV_PIX_FMT_NONE)
|
| + stream->codecpar->format = AV_PIX_FMT_YUV420P;
|
| }
|
| #endif
|
| } else if (codec_type == AVMEDIA_TYPE_SUBTITLE) {
|
| detected_text_track_count++;
|
| - if (codec_context->codec_id != AV_CODEC_ID_WEBVTT || !text_enabled_) {
|
| + if (codec_id != AV_CODEC_ID_WEBVTT || !text_enabled_) {
|
| continue;
|
| }
|
| } else {
|
| @@ -1292,17 +1285,6 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
|
| }
|
|
|
| StreamParser::TrackId track_id = stream->id;
|
| -
|
| - if ((codec_type == AVMEDIA_TYPE_AUDIO &&
|
| - media_tracks->getAudioConfig(track_id).IsValidConfig()) ||
|
| - (codec_type == AVMEDIA_TYPE_VIDEO &&
|
| - media_tracks->getVideoConfig(track_id).IsValidConfig())) {
|
| - MEDIA_LOG(INFO, media_log_)
|
| - << GetDisplayName()
|
| - << ": skipping duplicate media stream id=" << track_id;
|
| - continue;
|
| - }
|
| -
|
| std::string track_label = streams_[i]->GetMetadata("handler_name");
|
| std::string track_language = streams_[i]->GetMetadata("language");
|
|
|
| @@ -1316,6 +1298,16 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
|
| track_label = streams_[i]->GetMetadata("title");
|
| }
|
|
|
| + if ((codec_type == AVMEDIA_TYPE_AUDIO &&
|
| + media_tracks->getAudioConfig(track_id).IsValidConfig()) ||
|
| + (codec_type == AVMEDIA_TYPE_VIDEO &&
|
| + media_tracks->getVideoConfig(track_id).IsValidConfig())) {
|
| + MEDIA_LOG(INFO, media_log_)
|
| + << GetDisplayName()
|
| + << ": skipping duplicate media stream id=" << track_id;
|
| + continue;
|
| + }
|
| +
|
| // 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.
|
| MediaTrack* media_track = nullptr;
|
| @@ -1332,7 +1324,7 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
|
| } else if (codec_type == AVMEDIA_TYPE_VIDEO) {
|
| VideoDecoderConfig video_config = streams_[i]->video_decoder_config();
|
|
|
| - RecordVideoCodecStats(video_config, stream->codec->color_range,
|
| + RecordVideoCodecStats(video_config, stream->codecpar->color_range,
|
| media_log_.get());
|
|
|
| media_track = media_tracks->AddVideoTrack(video_config, track_id, "main",
|
| @@ -1405,9 +1397,9 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
|
| continue;
|
| const AVStream* audio_stream = stream->av_stream();
|
| DCHECK(audio_stream);
|
| - if (audio_stream->codec->codec_id == AV_CODEC_ID_OPUS ||
|
| + if (audio_stream->codecpar->codec_id == AV_CODEC_ID_OPUS ||
|
| (strcmp(format_context->iformat->name, "ogg") == 0 &&
|
| - audio_stream->codec->codec_id == AV_CODEC_ID_VORBIS)) {
|
| + audio_stream->codecpar->codec_id == AV_CODEC_ID_VORBIS)) {
|
| for (size_t i = 0; i < streams_.size(); ++i) {
|
| if (!streams_[i])
|
| continue;
|
| @@ -1487,10 +1479,12 @@ void FFmpegDemuxer::LogMetadata(AVFormatContext* avctx,
|
| std::string suffix = "";
|
| if (audio_track_count > 1)
|
| suffix = "_track" + base::IntToString(audio_track_count);
|
| - const AVCodecContext* audio_codec = avctx->streams[i]->codec;
|
| + const AVCodecParameters* audio_parameters = avctx->streams[i]->codecpar;
|
| const AudioDecoderConfig& audio_config = stream->audio_decoder_config();
|
| - params.SetString("audio_codec_name" + suffix, GetCodecName(audio_codec));
|
| - params.SetInteger("audio_channels_count" + suffix, audio_codec->channels);
|
| + params.SetString("audio_codec_name" + suffix,
|
| + GetCodecName(audio_parameters->codec_id));
|
| + params.SetInteger("audio_channels_count" + suffix,
|
| + audio_parameters->channels);
|
| params.SetString("audio_sample_format" + suffix,
|
| SampleFormatToString(audio_config.sample_format()));
|
| params.SetInteger("audio_samples_per_second" + suffix,
|
| @@ -1500,14 +1494,21 @@ void FFmpegDemuxer::LogMetadata(AVFormatContext* avctx,
|
| std::string suffix = "";
|
| if (video_track_count > 1)
|
| suffix = "_track" + base::IntToString(video_track_count);
|
| - const AVCodecContext* video_codec = avctx->streams[i]->codec;
|
| + const AVStream* video_av_stream = avctx->streams[i];
|
| + const AVCodecParameters* video_parameters = video_av_stream->codecpar;
|
| const VideoDecoderConfig& video_config = stream->video_decoder_config();
|
| - params.SetString("video_codec_name" + suffix, GetCodecName(video_codec));
|
| - params.SetInteger("width" + suffix, video_codec->width);
|
| - params.SetInteger("height" + suffix, video_codec->height);
|
| - params.SetString("time_base" + suffix,
|
| - base::StringPrintf("%d/%d", video_codec->time_base.num,
|
| - video_codec->time_base.den));
|
| + params.SetString("video_codec_name" + suffix,
|
| + GetCodecName(video_parameters->codec_id));
|
| + params.SetInteger("width" + suffix, video_parameters->width);
|
| + params.SetInteger("height" + suffix, video_parameters->height);
|
| +
|
| + // AVCodecParameters has no time_base field. We use the one from AVStream
|
| + // here.
|
| + params.SetString(
|
| + "time_base" + suffix,
|
| + base::StringPrintf("%d/%d", video_av_stream->time_base.num,
|
| + video_av_stream->time_base.den));
|
| +
|
| params.SetString("video_format" + suffix,
|
| VideoPixelFormatToString(video_config.format()));
|
| params.SetBoolean("video_is_encrypted" + suffix,
|
|
|