diff -up chromium-60.0.3112.101/media/base/audio_video_metadata_extractor.cc.0108 chromium-60.0.3112.101/media/base/audio_video_metadata_extractor.cc --- chromium-60.0.3112.101/media/base/audio_video_metadata_extractor.cc.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/base/audio_video_metadata_extractor.cc 2017-08-26 16:09:40.800000000 +0200 @@ -113,16 +113,16 @@ bool AudioVideoMetadataExtractor::Extrac // metadata to contained streams instead the container itself, like OGG. ExtractDictionary(stream->metadata, &info.tags); - if (!stream->codecpar) + if (!stream->codec) continue; - info.type = avcodec_get_name(stream->codecpar->codec_id); + info.type = avcodec_get_name(stream->codec->codec_id); // Extract dimensions of largest stream that's not an attached image. - if (stream->codecpar->width > 0 && stream->codecpar->width > width_ && - stream->codecpar->height > 0 && stream->codecpar->height > height_) { - width_ = stream->codecpar->width; - height_ = stream->codecpar->height; + if (stream->codec->width > 0 && stream->codec->width > width_ && + stream->codec->height > 0 && stream->codec->height > height_) { + width_ = stream->codec->width; + height_ = stream->codec->height; } // Extract attached image if requested. diff -up chromium-60.0.3112.101/media/base/audio_video_metadata_extractor_unittest.cc.0108 chromium-60.0.3112.101/media/base/audio_video_metadata_extractor_unittest.cc --- chromium-60.0.3112.101/media/base/audio_video_metadata_extractor_unittest.cc.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/base/audio_video_metadata_extractor_unittest.cc 2017-08-26 16:09:40.800000000 +0200 @@ -137,7 +137,7 @@ TEST(AudioVideoMetadataExtractorTest, An EXPECT_EQ(4u, extractor->stream_infos()[0].tags.size()); EXPECT_EQ("isom3gp4", GetTagValue(extractor->stream_infos()[0].tags, "compatible_brands")); - EXPECT_EQ("2014-02-11T00:39:25.000000Z", + EXPECT_EQ("2014-02-11 00:39:25", GetTagValue(extractor->stream_infos()[0].tags, "creation_time")); EXPECT_EQ("isom", GetTagValue(extractor->stream_infos()[0].tags, "major_brand")); @@ -146,7 +146,7 @@ TEST(AudioVideoMetadataExtractorTest, An EXPECT_EQ("h264", extractor->stream_infos()[1].type); EXPECT_EQ(5u, extractor->stream_infos()[1].tags.size()); - EXPECT_EQ("2014-02-11T00:39:25.000000Z", + EXPECT_EQ("2014-02-11 00:39:25", GetTagValue(extractor->stream_infos()[1].tags, "creation_time")); EXPECT_EQ("VideoHandle", GetTagValue(extractor->stream_infos()[1].tags, "handler_name")); @@ -155,7 +155,7 @@ TEST(AudioVideoMetadataExtractorTest, An EXPECT_EQ("aac", extractor->stream_infos()[2].type); EXPECT_EQ(3u, extractor->stream_infos()[2].tags.size()); - EXPECT_EQ("2014-02-11T00:39:25.000000Z", + EXPECT_EQ("2014-02-11 00:39:25", GetTagValue(extractor->stream_infos()[2].tags, "creation_time")); EXPECT_EQ("SoundHandle", GetTagValue(extractor->stream_infos()[2].tags, "handler_name")); diff -up chromium-60.0.3112.101/media/base/media_file_checker.cc.0108 chromium-60.0.3112.101/media/base/media_file_checker.cc --- chromium-60.0.3112.101/media/base/media_file_checker.cc.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/base/media_file_checker.cc 2017-08-26 16:09:40.800000000 +0200 @@ -13,7 +13,6 @@ #include "base/bind.h" #include "base/time/time.h" #include "media/ffmpeg/ffmpeg_common.h" -#include "media/ffmpeg/ffmpeg_deleters.h" #include "media/filters/blocking_url_protocol.h" #include "media/filters/ffmpeg_glue.h" #include "media/filters/file_data_source.h" @@ -45,20 +44,14 @@ bool MediaFileChecker::Start(base::TimeD return false; // Remember the codec context for any decodable audio or video streams. - std::map<int, std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext>> - stream_contexts; + std::map<int, AVCodecContext*> stream_contexts; for (size_t i = 0; i < format_context->nb_streams; ++i) { - AVCodecParameters* cp = format_context->streams[i]->codecpar; - - if (cp->codec_type == AVMEDIA_TYPE_AUDIO || - cp->codec_type == AVMEDIA_TYPE_VIDEO) { - std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> c( - AVStreamToAVCodecContext(format_context->streams[i])); - if (!c) - continue; - AVCodec* codec = avcodec_find_decoder(cp->codec_id); - if (codec && avcodec_open2(c.get(), codec, nullptr) >= 0) - stream_contexts[i] = std::move(c); + AVCodecContext* c = format_context->streams[i]->codec; + if (c->codec_type == AVMEDIA_TYPE_AUDIO || + c->codec_type == AVMEDIA_TYPE_VIDEO) { + AVCodec* codec = avcodec_find_decoder(c->codec_id); + if (codec && avcodec_open2(c, codec, NULL) >= 0) + stream_contexts[i] = c; } } @@ -77,13 +70,13 @@ bool MediaFileChecker::Start(base::TimeD if (result < 0) break; - std::map<int, std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext>>:: - const_iterator it = stream_contexts.find(packet.stream_index); + std::map<int, AVCodecContext*>::const_iterator it = + stream_contexts.find(packet.stream_index); if (it == stream_contexts.end()) { av_packet_unref(&packet); continue; } - AVCodecContext* av_context = it->second.get(); + AVCodecContext* av_context = it->second; int frame_decoded = 0; if (av_context->codec_type == AVMEDIA_TYPE_AUDIO) { @@ -109,7 +102,6 @@ bool MediaFileChecker::Start(base::TimeD av_packet_unref(&packet); } while (base::TimeTicks::Now() < deadline && read_ok && result >= 0); - stream_contexts.clear(); return read_ok && (result == AVERROR_EOF || result >= 0); } diff -up chromium-60.0.3112.101/media/cast/test/fake_media_source.cc.0108 chromium-60.0.3112.101/media/cast/test/fake_media_source.cc --- chromium-60.0.3112.101/media/cast/test/fake_media_source.cc.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/cast/test/fake_media_source.cc 2017-08-26 16:09:40.800000000 +0200 @@ -138,14 +138,7 @@ void FakeMediaSource::SetSourceFile(cons // Prepare FFmpeg decoders. for (unsigned int i = 0; i < av_format_context_->nb_streams; ++i) { AVStream* av_stream = av_format_context_->streams[i]; - std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> av_codec_context( - AVStreamToAVCodecContext(av_stream)); - if (!av_codec_context) { - LOG(ERROR) << "Cannot get a codec context for the codec: " - << av_stream->codecpar->codec_id; - continue; - } - + AVCodecContext* av_codec_context = av_stream->codec; AVCodec* av_codec = avcodec_find_decoder(av_codec_context->codec_id); if (!av_codec) { @@ -159,7 +152,7 @@ void FakeMediaSource::SetSourceFile(cons av_codec_context->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK; av_codec_context->request_sample_fmt = AV_SAMPLE_FMT_S16; - if (avcodec_open2(av_codec_context.get(), av_codec, nullptr) < 0) { + if (avcodec_open2(av_codec_context, av_codec, NULL) < 0) { LOG(ERROR) << "Cannot open AVCodecContext for the codec: " << av_codec_context->codec_id; return; @@ -181,14 +174,14 @@ void FakeMediaSource::SetSourceFile(cons LOG(WARNING) << "Found multiple audio streams."; } audio_stream_index_ = static_cast<int>(i); - av_audio_context_ = std::move(av_codec_context); source_audio_params_.Reset( - AudioParameters::AUDIO_PCM_LINEAR, layout, - av_audio_context_->sample_rate, - 8 * av_get_bytes_per_sample(av_audio_context_->sample_fmt), - av_audio_context_->sample_rate / kAudioPacketsPerSecond); + AudioParameters::AUDIO_PCM_LINEAR, + layout, + av_codec_context->sample_rate, + 8 * av_get_bytes_per_sample(av_codec_context->sample_fmt), + av_codec_context->sample_rate / kAudioPacketsPerSecond); source_audio_params_.set_channels_for_discrete( - av_audio_context_->channels); + av_codec_context->channels); CHECK(source_audio_params_.IsValid()); LOG(INFO) << "Source file has audio."; } else if (av_codec->type == AVMEDIA_TYPE_VIDEO) { @@ -202,7 +195,6 @@ void FakeMediaSource::SetSourceFile(cons LOG(WARNING) << "Found multiple video streams."; } video_stream_index_ = static_cast<int>(i); - av_video_context_ = std::move(av_codec_context); if (final_fps > 0) { // If video is played at a manual speed audio needs to match. playback_rate_ = 1.0 * final_fps * @@ -465,8 +457,8 @@ void FakeMediaSource::DecodeAudio(Scoped do { int frame_decoded = 0; - int result = avcodec_decode_audio4(av_audio_context_.get(), avframe, - &frame_decoded, &packet_temp); + int result = avcodec_decode_audio4( + av_audio_context(), avframe, &frame_decoded, &packet_temp); CHECK(result >= 0) << "Failed to decode audio."; packet_temp.size -= result; packet_temp.data += result; @@ -490,20 +482,21 @@ void FakeMediaSource::DecodeAudio(Scoped } scoped_refptr<AudioBuffer> buffer = AudioBuffer::CopyFrom( - AVSampleFormatToSampleFormat(av_audio_context_->sample_fmt, - av_audio_context_->codec_id), - ChannelLayoutToChromeChannelLayout(av_audio_context_->channel_layout, - av_audio_context_->channels), - av_audio_context_->channels, av_audio_context_->sample_rate, + AVSampleFormatToSampleFormat(av_audio_context()->sample_fmt, + av_audio_context()->codec_id), + ChannelLayoutToChromeChannelLayout(av_audio_context()->channel_layout, + av_audio_context()->channels), + av_audio_context()->channels, av_audio_context()->sample_rate, frames_read, &avframe->data[0], - PtsToTimeDelta(avframe->pts, av_audio_stream()->time_base)); + PtsToTimeDelta(avframe->pkt_pts, av_audio_stream()->time_base)); audio_algo_.EnqueueBuffer(buffer); av_frame_unref(avframe); } while (packet_temp.size > 0); av_frame_free(&avframe); const int frames_needed_to_scale = - playback_rate_ * av_audio_context_->sample_rate / kAudioPacketsPerSecond; + playback_rate_ * av_audio_context()->sample_rate / + kAudioPacketsPerSecond; while (frames_needed_to_scale <= audio_algo_.frames_buffered()) { if (!audio_algo_.FillBuffer(audio_fifo_input_bus_.get(), 0, audio_fifo_input_bus_->frames(), @@ -538,29 +531,29 @@ void FakeMediaSource::DecodeVideo(Scoped // Video. int got_picture; AVFrame* avframe = av_frame_alloc(); - CHECK(avcodec_decode_video2(av_video_context_.get(), avframe, &got_picture, - packet.get()) >= 0) + CHECK(avcodec_decode_video2( + av_video_context(), avframe, &got_picture, packet.get()) >= 0) << "Video decode error."; if (!got_picture) { av_frame_free(&avframe); return; } - gfx::Size size(av_video_context_->width, av_video_context_->height); + gfx::Size size(av_video_context()->width, av_video_context()->height); if (!video_first_pts_set_) { - video_first_pts_ = avframe->pts; + video_first_pts_ = avframe->pkt_pts; video_first_pts_set_ = true; } const AVRational& time_base = av_video_stream()->time_base; base::TimeDelta timestamp = - PtsToTimeDelta(avframe->pts - video_first_pts_, time_base); + PtsToTimeDelta(avframe->pkt_pts - video_first_pts_, time_base); if (timestamp < last_video_frame_timestamp_) { // Stream has rewound. Rebase |video_first_pts_|. const AVRational& frame_rate = av_video_stream()->r_frame_rate; timestamp = last_video_frame_timestamp_ + (base::TimeDelta::FromSeconds(1) * frame_rate.den / frame_rate.num); const int64_t adjustment_pts = TimeDeltaToPts(timestamp, time_base); - video_first_pts_ = avframe->pts - adjustment_pts; + video_first_pts_ = avframe->pkt_pts - adjustment_pts; } scoped_refptr<media::VideoFrame> video_frame = @@ -627,5 +620,13 @@ AVStream* FakeMediaSource::av_video_stre return av_format_context_->streams[video_stream_index_]; } +AVCodecContext* FakeMediaSource::av_audio_context() { + return av_audio_stream()->codec; +} + +AVCodecContext* FakeMediaSource::av_video_context() { + return av_video_stream()->codec; +} + } // namespace cast } // namespace media diff -up chromium-60.0.3112.101/media/cast/test/fake_media_source.h.0108 chromium-60.0.3112.101/media/cast/test/fake_media_source.h --- chromium-60.0.3112.101/media/cast/test/fake_media_source.h.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/cast/test/fake_media_source.h 2017-08-26 16:09:40.800000000 +0200 @@ -40,8 +40,6 @@ class FFmpegGlue; class InMemoryUrlProtocol; class VideoFrame; -struct ScopedPtrAVFreeContext; - namespace cast { class AudioFrameInput; @@ -115,6 +113,8 @@ class FakeMediaSource : public media::Au AVStream* av_audio_stream(); AVStream* av_video_stream(); + AVCodecContext* av_audio_context(); + AVCodecContext* av_video_context(); const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; const media::AudioParameters output_audio_params_; @@ -142,12 +142,10 @@ class FakeMediaSource : public media::Au AVFormatContext* av_format_context_; int audio_stream_index_; - std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> av_audio_context_; AudioParameters source_audio_params_; double playback_rate_; int video_stream_index_; - std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> av_video_context_; int video_frame_rate_numerator_; int video_frame_rate_denominator_; diff -up chromium-60.0.3112.101/media/ffmpeg/ffmpeg_common.cc.0108 chromium-60.0.3112.101/media/ffmpeg/ffmpeg_common.cc --- chromium-60.0.3112.101/media/ffmpeg/ffmpeg_common.cc.0108 2017-08-26 16:09:40.670000000 +0200 +++ chromium-60.0.3112.101/media/ffmpeg/ffmpeg_common.cc 2017-08-26 16:15:30.800000000 +0200 @@ -392,27 +392,10 @@ bool AVCodecContextToAudioDecoderConfig( return true; } -std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> -AVStreamToAVCodecContext(const AVStream* stream) { - std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> codec_context( - avcodec_alloc_context3(nullptr)); - if (avcodec_parameters_to_context(codec_context.get(), stream->codecpar) < - 0) { - return nullptr; - } - - return codec_context; -} - bool AVStreamToAudioDecoderConfig(const AVStream* stream, AudioDecoderConfig* config) { - std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> codec_context( - AVStreamToAVCodecContext(stream)); - if (!codec_context) - return false; - return AVCodecContextToAudioDecoderConfig( - codec_context.get(), GetEncryptionScheme(stream), config); + stream->codec, GetEncryptionScheme(stream), config); } void AudioDecoderConfigToAVCodecContext(const AudioDecoderConfig& config, @@ -445,26 +428,22 @@ void AudioDecoderConfigToAVCodecContext( bool AVStreamToVideoDecoderConfig(const AVStream* stream, VideoDecoderConfig* config) { - std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> codec_context( - AVStreamToAVCodecContext(stream)); - if (!codec_context) - return false; - - // AVStream.codec->coded_{width,height} access is deprecated in ffmpeg. - // Use just the width and height as hints of coded size. - gfx::Size coded_size(codec_context->width, codec_context->height); + // Anticipating AVStream.codec.coded_{width,height} will be inaccessible in + // ffmpeg soon, just use the width and height, padded below, as hints of the + // coded size. + gfx::Size coded_size(stream->codec->width, stream->codec->height); // TODO(vrk): This assumes decoded frame data starts at (0, 0), which is true // for now, but may not always be true forever. Fix this in the future. - gfx::Rect visible_rect(codec_context->width, codec_context->height); + gfx::Rect visible_rect(stream->codec->width, stream->codec->height); AVRational aspect_ratio = { 1, 1 }; if (stream->sample_aspect_ratio.num) aspect_ratio = stream->sample_aspect_ratio; - else if (codec_context->sample_aspect_ratio.num) - aspect_ratio = codec_context->sample_aspect_ratio; + else if (stream->codec->sample_aspect_ratio.num) + aspect_ratio = stream->codec->sample_aspect_ratio; - VideoCodec codec = CodecIDToVideoCodec(codec_context->codec_id); + VideoCodec codec = CodecIDToVideoCodec(stream->codec->codec_id); VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; if (codec == kCodecVP8) @@ -474,7 +453,7 @@ bool AVStreamToVideoDecoderConfig(const // crbug.com/592074 profile = VP9PROFILE_PROFILE0; else - profile = ProfileIDToVideoCodecProfile(codec_context->profile); + profile = ProfileIDToVideoCodecProfile(stream->codec->profile); // Without the FFmpeg h264 decoder, AVFormat is unable to get the profile, so // default to baseline and let the VDA fail later if it doesn't support the @@ -489,7 +468,7 @@ bool AVStreamToVideoDecoderConfig(const visible_rect.size(), aspect_ratio.num, aspect_ratio.den); VideoPixelFormat format = - AVPixelFormatToVideoPixelFormat(codec_context->pix_fmt); + AVPixelFormatToVideoPixelFormat(stream->codec->pix_fmt); // The format and coded size may be unknown if FFmpeg is compiled without // video decoders. #if defined(DISABLE_FFMPEG_VIDEO_DECODERS) @@ -519,8 +498,8 @@ bool AVStreamToVideoDecoderConfig(const } // Prefer the color space found by libavcodec if available. - ColorSpace color_space = AVColorSpaceToColorSpace(codec_context->colorspace, - codec_context->color_range); + ColorSpace color_space = AVColorSpaceToColorSpace(stream->codec->colorspace, + stream->codec->color_range); if (color_space == COLOR_SPACE_UNSPECIFIED) { // Otherwise, assume that SD video is usually Rec.601, and HD is usually // Rec.709. @@ -528,30 +507,30 @@ bool AVStreamToVideoDecoderConfig(const : COLOR_SPACE_HD_REC709; } - // AVCodecContext occasionally has invalid extra data. See - // http://crbug.com/517163 - if (codec_context->extradata != nullptr && - codec_context->extradata_size == 0) { - LOG(ERROR) << __func__ << " Non-Null extra data cannot have size of 0."; + // AVStream occasionally has invalid extra data. See http://crbug.com/517163 + if ((stream->codec->extradata_size == 0) != + (stream->codec->extradata == nullptr)) { + LOG(ERROR) << __func__ + << (stream->codec->extradata == nullptr ? " NULL" : " Non-Null") + << " extra data cannot have size of " + << stream->codec->extradata_size << "."; return false; } - CHECK_EQ(codec_context->extradata == nullptr, - codec_context->extradata_size == 0); std::vector<uint8_t> extra_data; - if (codec_context->extradata_size > 0) { - extra_data.assign(codec_context->extradata, - codec_context->extradata + codec_context->extradata_size); + if (stream->codec->extradata_size > 0) { + extra_data.assign(stream->codec->extradata, + stream->codec->extradata + stream->codec->extradata_size); } config->Initialize(codec, profile, format, color_space, coded_size, visible_rect, natural_size, extra_data, GetEncryptionScheme(stream)); - const AVCodecParameters* codec_parameters = stream->codecpar; + const AVCodecContext* codec_context = stream->codec; config->set_color_space_info(VideoColorSpace( - codec_parameters->color_primaries, codec_parameters->color_trc, - codec_parameters->color_space, - codec_parameters->color_range == AVCOL_RANGE_JPEG + codec_context->color_primaries, codec_context->color_trc, + codec_context->colorspace, + codec_context->color_range == AVCOL_RANGE_JPEG ? gfx::ColorSpace::RangeID::FULL : gfx::ColorSpace::RangeID::LIMITED)); @@ -756,6 +735,45 @@ std::string AVErrorToString(int errnum) return std::string(errbuf); } +bool FFmpegUTCDateToTime(const char* date_utc, base::Time* out) { + DCHECK(date_utc); + DCHECK(out); + + std::vector<base::StringPiece> fields = base::SplitStringPiece( + date_utc, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + if (fields.size() != 2) + return false; + + std::vector<base::StringPiece> date_fields = base::SplitStringPiece( + fields[0], "-", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + if (date_fields.size() != 3) + return false; + + // TODO(acolwell): Update this parsing code when FFmpeg returns sub-second + // information. + std::vector<base::StringPiece> time_fields = base::SplitStringPiece( + fields[1], ":", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + if (time_fields.size() != 3) + return false; + + base::Time::Exploded exploded; + exploded.millisecond = 0; + // This field cannot be uninitialized. Unless not modified, make it 0 here + // then. + exploded.day_of_week = 0; + if (base::StringToInt(date_fields[0], &exploded.year) && + base::StringToInt(date_fields[1], &exploded.month) && + base::StringToInt(date_fields[2], &exploded.day_of_month) && + base::StringToInt(time_fields[0], &exploded.hour) && + base::StringToInt(time_fields[1], &exploded.minute) && + base::StringToInt(time_fields[2], &exploded.second)) { + if (base::Time::FromUTCExploded(exploded, out)) + return true; + } + + return false; +} + int32_t HashCodecName(const char* codec_name) { // Use the first 32-bits from the SHA1 hash as the identifier. int32_t hash; diff -up chromium-60.0.3112.101/media/ffmpeg/ffmpeg_common.h.0108 chromium-60.0.3112.101/media/ffmpeg/ffmpeg_common.h --- chromium-60.0.3112.101/media/ffmpeg/ffmpeg_common.h.0108 2017-08-26 16:16:12.880000000 +0200 +++ chromium-60.0.3112.101/media/ffmpeg/ffmpeg_common.h 2017-08-26 16:09:40.810000000 +0200 @@ -102,12 +102,6 @@ MEDIA_EXPORT int64_t ConvertToTimeBase(c // Converts an FFmpeg audio codec ID into its corresponding supported codec id. MEDIA_EXPORT AudioCodec CodecIDToAudioCodec(AVCodecID codec_id); -// Allocates, populates and returns a wrapped AVCodecContext from the -// AVCodecParameters in |stream|. On failure, returns a wrapped nullptr. -// Wrapping helps ensure eventual destruction of the AVCodecContext. -MEDIA_EXPORT std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> -AVStreamToAVCodecContext(const AVStream* stream); - // Returns true if AVStream is successfully converted to a AudioDecoderConfig. // Returns false if conversion fails, in which case |config| is not modified. MEDIA_EXPORT bool AVStreamToAudioDecoderConfig(const AVStream* stream, @@ -159,6 +153,11 @@ ColorSpace AVColorSpaceToColorSpace(AVCo // Converts an AVERROR error number to a description. std::string AVErrorToString(int errnum); +// Convert FFmpeg UTC representation (YYYY-MM-DD HH:MM:SS) to base::Time. +// Returns true and sets |*out| if |date_utc| contains a valid +// date string. Otherwise returns fals and timeline_offset is unmodified. +MEDIA_EXPORT bool FFmpegUTCDateToTime(const char* date_utc, base::Time* out); + // Returns a 32-bit hash for the given codec name. See the VerifyUmaCodecHashes // unit test for more information and code for generating the histogram XML. MEDIA_EXPORT int32_t HashCodecName(const char* codec_name); diff -up chromium-60.0.3112.101/media/ffmpeg/ffmpeg_common_unittest.cc.0108 chromium-60.0.3112.101/media/ffmpeg/ffmpeg_common_unittest.cc --- chromium-60.0.3112.101/media/ffmpeg/ffmpeg_common_unittest.cc.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/ffmpeg/ffmpeg_common_unittest.cc 2017-08-26 16:09:40.810000000 +0200 @@ -42,43 +42,40 @@ void TestConfigConvertExtraData( EXPECT_TRUE(converter_fn.Run(stream, decoder_config)); // Store orig to let FFmpeg free whatever it allocated. - AVCodecParameters* codec_parameters = stream->codecpar; - uint8_t* orig_extradata = codec_parameters->extradata; - int orig_extradata_size = codec_parameters->extradata_size; - - // Valid combination: extra_data = nullptr && size = 0. - codec_parameters->extradata = nullptr; - codec_parameters->extradata_size = 0; + AVCodecContext* codec_context = stream->codec; + uint8_t* orig_extradata = codec_context->extradata; + int orig_extradata_size = codec_context->extradata_size; + + // Valid combination: extra_data = NULL && size = 0. + codec_context->extradata = NULL; + codec_context->extradata_size = 0; EXPECT_TRUE(converter_fn.Run(stream, decoder_config)); - EXPECT_EQ(static_cast<size_t>(codec_parameters->extradata_size), + EXPECT_EQ(static_cast<size_t>(codec_context->extradata_size), decoder_config->extra_data().size()); - // Valid combination: extra_data = non-nullptr && size > 0. - codec_parameters->extradata = &kExtraData[0]; - codec_parameters->extradata_size = arraysize(kExtraData); + // Valid combination: extra_data = non-NULL && size > 0. + codec_context->extradata = &kExtraData[0]; + codec_context->extradata_size = arraysize(kExtraData); EXPECT_TRUE(converter_fn.Run(stream, decoder_config)); - EXPECT_EQ(static_cast<size_t>(codec_parameters->extradata_size), + EXPECT_EQ(static_cast<size_t>(codec_context->extradata_size), decoder_config->extra_data().size()); - EXPECT_EQ( - 0, memcmp(codec_parameters->extradata, &decoder_config->extra_data()[0], - decoder_config->extra_data().size())); - - // Possible combination: extra_data = nullptr && size != 0, but the converter - // function considers this valid and having no extra_data, due to behavior of - // avcodec_parameters_to_context(). - codec_parameters->extradata = nullptr; - codec_parameters->extradata_size = 10; - EXPECT_TRUE(converter_fn.Run(stream, decoder_config)); - EXPECT_EQ(0UL, decoder_config->extra_data().size()); + EXPECT_EQ(0, memcmp(codec_context->extradata, + &decoder_config->extra_data()[0], + decoder_config->extra_data().size())); + + // Invalid combination: extra_data = NULL && size != 0. + codec_context->extradata = NULL; + codec_context->extradata_size = 10; + EXPECT_FALSE(converter_fn.Run(stream, decoder_config)); - // Invalid combination: extra_data = non-nullptr && size = 0. - codec_parameters->extradata = &kExtraData[0]; - codec_parameters->extradata_size = 0; + // Invalid combination: extra_data = non-NULL && size = 0. + codec_context->extradata = &kExtraData[0]; + codec_context->extradata_size = 0; EXPECT_FALSE(converter_fn.Run(stream, decoder_config)); // Restore orig values for sane cleanup. - codec_parameters->extradata = orig_extradata; - codec_parameters->extradata_size = orig_extradata_size; + codec_context->extradata = orig_extradata; + codec_context->extradata_size = orig_extradata_size; } TEST_F(FFmpegCommonTest, AVStreamToDecoderConfig) { @@ -98,8 +95,8 @@ TEST_F(FFmpegCommonTest, AVStreamToDecod i < format_context->nb_streams && (!found_audio || !found_video); ++i) { AVStream* stream = format_context->streams[i]; - AVCodecParameters* codec_parameters = stream->codecpar; - AVMediaType codec_type = codec_parameters->codec_type; + AVCodecContext* codec_context = stream->codec; + AVMediaType codec_type = codec_context->codec_type; if (codec_type == AVMEDIA_TYPE_AUDIO) { if (found_audio) @@ -170,6 +167,59 @@ TEST_F(FFmpegCommonTest, VerifyFormatSiz } } +TEST_F(FFmpegCommonTest, UTCDateToTime_Valid) { + base::Time result; + EXPECT_TRUE(FFmpegUTCDateToTime("2012-11-10 12:34:56", &result)); + + base::Time::Exploded exploded; + result.UTCExplode(&exploded); + EXPECT_TRUE(exploded.HasValidValues()); + EXPECT_EQ(2012, exploded.year); + EXPECT_EQ(11, exploded.month); + EXPECT_EQ(6, exploded.day_of_week); + EXPECT_EQ(10, exploded.day_of_month); + EXPECT_EQ(12, exploded.hour); + EXPECT_EQ(34, exploded.minute); + EXPECT_EQ(56, exploded.second); + EXPECT_EQ(0, exploded.millisecond); +} + +TEST_F(FFmpegCommonTest, UTCDateToTime_Invalid) { + const char* invalid_date_strings[] = { + "", + "2012-11-10", + "12:34:56", + "-- ::", + "2012-11-10 12:34:", + "2012-11-10 12::56", + "2012-11-10 :34:56", + "2012-11- 12:34:56", + "2012--10 12:34:56", + "-11-10 12:34:56", + "2012-11 12:34:56", + "2012-11-10-12 12:34:56", + "2012-11-10 12:34", + "2012-11-10 12:34:56:78", + "ABCD-11-10 12:34:56", + "2012-EF-10 12:34:56", + "2012-11-GH 12:34:56", + "2012-11-10 IJ:34:56", + "2012-11-10 12:JL:56", + "2012-11-10 12:34:MN", + "2012-11-10 12:34:56.123", + "2012-11-1012:34:56", + "2012-11-10 12:34:56 UTC", + }; + + for (size_t i = 0; i < arraysize(invalid_date_strings); ++i) { + const char* date_string = invalid_date_strings[i]; + base::Time result; + EXPECT_FALSE(FFmpegUTCDateToTime(date_string, &result)) + << "date_string '" << date_string << "'"; + EXPECT_TRUE(result.is_null()); + } +} + // Verifies there are no collisions of the codec name hashes used for UMA. Also // includes code for updating the histograms XML. TEST_F(FFmpegCommonTest, VerifyUmaCodecHashes) { diff -up chromium-60.0.3112.101/media/ffmpeg/ffmpeg_regression_tests.cc.0108 chromium-60.0.3112.101/media/ffmpeg/ffmpeg_regression_tests.cc --- chromium-60.0.3112.101/media/ffmpeg/ffmpeg_regression_tests.cc.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/ffmpeg/ffmpeg_regression_tests.cc 2017-08-26 16:09:40.810000000 +0200 @@ -140,13 +140,13 @@ FFMPEG_TEST_CASE(Cr152691, FFMPEG_TEST_CASE(Cr161639, "security/161639.m4a", PIPELINE_OK, PIPELINE_OK); FFMPEG_TEST_CASE(Cr222754, "security/222754.mp4", - DEMUXER_ERROR_NO_SUPPORTED_STREAMS, - DEMUXER_ERROR_NO_SUPPORTED_STREAMS); + PIPELINE_OK, + PIPELINE_ERROR_DECODE); FFMPEG_TEST_CASE(Cr234630a, "security/234630a.mov", PIPELINE_OK, PIPELINE_OK); FFMPEG_TEST_CASE(Cr234630b, "security/234630b.mov", - DEMUXER_ERROR_NO_SUPPORTED_STREAMS, - DEMUXER_ERROR_NO_SUPPORTED_STREAMS); + PIPELINE_OK, + PIPELINE_ERROR_DECODE); FFMPEG_TEST_CASE(Cr242786, "security/242786.webm", PIPELINE_OK, PIPELINE_OK); // Test for out-of-bounds access with slightly corrupt file (detection logic // thinks it's a MONO file, but actually contains STEREO audio). diff -up chromium-60.0.3112.101/media/filters/audio_file_reader.cc.0108 chromium-60.0.3112.101/media/filters/audio_file_reader.cc --- chromium-60.0.3112.101/media/filters/audio_file_reader.cc.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/filters/audio_file_reader.cc 2017-08-26 16:09:40.810000000 +0200 @@ -23,7 +23,8 @@ static const int kAACPrimingFrameCount = static const int kAACRemainderFrameCount = 519; AudioFileReader::AudioFileReader(FFmpegURLProtocol* protocol) - : stream_index_(0), + : codec_context_(NULL), + stream_index_(0), protocol_(protocol), audio_codec_(kUnknownAudioCodec), channels_(0), @@ -48,19 +49,19 @@ bool AudioFileReader::OpenDemuxer() { return false; } - // Find the first audio stream, if any. - codec_context_.reset(); - bool found_stream = false; + // Get the codec context. + codec_context_ = NULL; for (size_t i = 0; i < format_context->nb_streams; ++i) { - if (format_context->streams[i]->codecpar->codec_type == - AVMEDIA_TYPE_AUDIO) { + AVCodecContext* c = format_context->streams[i]->codec; + if (c->codec_type == AVMEDIA_TYPE_AUDIO) { + codec_context_ = c; stream_index_ = i; - found_stream = true; break; } } - if (!found_stream) + // Get the codec. + if (!codec_context_) return false; const int result = avformat_find_stream_info(format_context, NULL); @@ -70,13 +71,6 @@ bool AudioFileReader::OpenDemuxer() { return false; } - // Get the codec context. - codec_context_ = - AVStreamToAVCodecContext(format_context->streams[stream_index_]); - if (!codec_context_) - return false; - - DCHECK_EQ(codec_context_->codec_type, AVMEDIA_TYPE_AUDIO); return true; } @@ -87,7 +81,7 @@ bool AudioFileReader::OpenDecoder() { if (codec_context_->sample_fmt == AV_SAMPLE_FMT_S16P) codec_context_->request_sample_fmt = AV_SAMPLE_FMT_S16; - const int result = avcodec_open2(codec_context_.get(), codec, nullptr); + const int result = avcodec_open2(codec_context_, codec, NULL); if (result < 0) { DLOG(WARNING) << "AudioFileReader::Open() : could not open codec -" << " result: " << result; @@ -127,8 +121,10 @@ bool AudioFileReader::HasKnownDuration() } void AudioFileReader::Close() { - codec_context_.reset(); + // |codec_context_| is a stream inside glue_->format_context(), so it is + // closed when |glue_| is disposed. glue_.reset(); + codec_context_ = NULL; } int AudioFileReader::Read( @@ -153,8 +149,8 @@ int AudioFileReader::Read( av_frame_unref(av_frame.get()); int frame_decoded = 0; - int result = avcodec_decode_audio4(codec_context_.get(), av_frame.get(), - &frame_decoded, &packet_temp); + int result = avcodec_decode_audio4( + codec_context_, av_frame.get(), &frame_decoded, &packet_temp); if (result < 0) { // Unable to decode this current packet. We'll skip it and @@ -277,12 +273,10 @@ bool AudioFileReader::ReadPacket(AVPacke } bool AudioFileReader::SeekForTesting(base::TimeDelta seek_time) { - // Use the AVStream's time_base, since |codec_context_| does not have - // time_base populated until after OpenDecoder(). - return av_seek_frame( - glue_->format_context(), stream_index_, - ConvertToTimeBase(GetAVStreamForTesting()->time_base, seek_time), - AVSEEK_FLAG_BACKWARD) >= 0; + return av_seek_frame(glue_->format_context(), + stream_index_, + ConvertToTimeBase(codec_context_->time_base, seek_time), + AVSEEK_FLAG_BACKWARD) >= 0; } const AVStream* AudioFileReader::GetAVStreamForTesting() const { diff -up chromium-60.0.3112.101/media/filters/audio_file_reader.h.0108 chromium-60.0.3112.101/media/filters/audio_file_reader.h --- chromium-60.0.3112.101/media/filters/audio_file_reader.h.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/filters/audio_file_reader.h 2017-08-26 16:09:40.810000000 +0200 @@ -11,7 +11,6 @@ #include "base/macros.h" #include "media/base/audio_codecs.h" #include "media/base/media_export.h" -#include "media/ffmpeg/ffmpeg_deleters.h" #include "media/filters/ffmpeg_glue.h" struct AVCodecContext; @@ -82,7 +81,7 @@ class MEDIA_EXPORT AudioFileReader { const AVStream* GetAVStreamForTesting() const; const AVCodecContext* codec_context_for_testing() const { - return codec_context_.get(); + return codec_context_; } private: @@ -90,10 +89,8 @@ class MEDIA_EXPORT AudioFileReader { bool OpenDecoder(); bool ReadPacket(AVPacket* output_packet); - // Destruct |glue_| after |codec_context_|. std::unique_ptr<FFmpegGlue> glue_; - std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> codec_context_; - + AVCodecContext* codec_context_; int stream_index_; FFmpegURLProtocol* protocol_; AudioCodec audio_codec_; diff -up chromium-60.0.3112.101/media/filters/ffmpeg_aac_bitstream_converter.cc.0108 chromium-60.0.3112.101/media/filters/ffmpeg_aac_bitstream_converter.cc --- chromium-60.0.3112.101/media/filters/ffmpeg_aac_bitstream_converter.cc.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/filters/ffmpeg_aac_bitstream_converter.cc 2017-08-26 16:09:40.810000000 +0200 @@ -157,15 +157,15 @@ bool GenerateAdtsHeader(int codec, } FFmpegAACBitstreamConverter::FFmpegAACBitstreamConverter( - AVCodecParameters* stream_codec_parameters) - : stream_codec_parameters_(stream_codec_parameters), + AVCodecContext* stream_codec_context) + : stream_codec_context_(stream_codec_context), header_generated_(false), codec_(), audio_profile_(), sample_rate_index_(), channel_configuration_(), frame_length_() { - CHECK(stream_codec_parameters_); + CHECK(stream_codec_context_); } FFmpegAACBitstreamConverter::~FFmpegAACBitstreamConverter() { @@ -178,44 +178,45 @@ bool FFmpegAACBitstreamConverter::Conver int header_plus_packet_size = packet->size + kAdtsHeaderSize; - if (!stream_codec_parameters_->extradata) { + if (!stream_codec_context_->extradata) { DLOG(ERROR) << "extradata is null"; return false; } - if (stream_codec_parameters_->extradata_size < 2) { + if (stream_codec_context_->extradata_size < 2) { DLOG(ERROR) << "extradata too small to contain MP4A header"; return false; } int sample_rate_index = - ((stream_codec_parameters_->extradata[0] & 0x07) << 1) | - ((stream_codec_parameters_->extradata[1] & 0x80) >> 7); + ((stream_codec_context_->extradata[0] & 0x07) << 1) | + ((stream_codec_context_->extradata[1] & 0x80) >> 7); if (sample_rate_index > 12) { sample_rate_index = 4; } - if (!header_generated_ || codec_ != stream_codec_parameters_->codec_id || - audio_profile_ != stream_codec_parameters_->profile || + if (!header_generated_ || + codec_ != stream_codec_context_->codec_id || + audio_profile_ != stream_codec_context_->profile || sample_rate_index_ != sample_rate_index || - channel_configuration_ != stream_codec_parameters_->channels || + channel_configuration_ != stream_codec_context_->channels || frame_length_ != header_plus_packet_size) { - header_generated_ = - GenerateAdtsHeader(stream_codec_parameters_->codec_id, - 0, // layer - stream_codec_parameters_->profile, sample_rate_index, - 0, // private stream - stream_codec_parameters_->channels, - 0, // originality - 0, // home - 0, // copyrighted_stream - 0, // copyright_ start - header_plus_packet_size, - 0x7FF, // buffer fullness - 0, // one frame per packet - hdr_); - codec_ = stream_codec_parameters_->codec_id; - audio_profile_ = stream_codec_parameters_->profile; + header_generated_ = GenerateAdtsHeader(stream_codec_context_->codec_id, + 0, // layer + stream_codec_context_->profile, + sample_rate_index, + 0, // private stream + stream_codec_context_->channels, + 0, // originality + 0, // home + 0, // copyrighted_stream + 0, // copyright_ start + header_plus_packet_size, + 0x7FF, // buffer fullness + 0, // one frame per packet + hdr_); + codec_ = stream_codec_context_->codec_id; + audio_profile_ = stream_codec_context_->profile; sample_rate_index_ = sample_rate_index; - channel_configuration_ = stream_codec_parameters_->channels; + channel_configuration_ = stream_codec_context_->channels; frame_length_ = header_plus_packet_size; } diff -up chromium-60.0.3112.101/media/filters/ffmpeg_aac_bitstream_converter.h.0108 chromium-60.0.3112.101/media/filters/ffmpeg_aac_bitstream_converter.h --- chromium-60.0.3112.101/media/filters/ffmpeg_aac_bitstream_converter.h.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/filters/ffmpeg_aac_bitstream_converter.h 2017-08-26 16:09:40.810000000 +0200 @@ -13,7 +13,7 @@ #include "media/filters/ffmpeg_bitstream_converter.h" // Forward declarations for FFmpeg datatypes used. -struct AVCodecParameters; +struct AVCodecContext; struct AVPacket; namespace media { @@ -24,11 +24,10 @@ class MEDIA_EXPORT FFmpegAACBitstreamCon public: enum { kAdtsHeaderSize = 7 }; - // The |stream_codec_parameters| will be used during conversion and should be - // the AVCodecParameters for the stream sourcing these packets. A reference to - // |stream_codec_parameters| is retained, so it must outlive this class. - explicit FFmpegAACBitstreamConverter( - AVCodecParameters* stream_codec_parameters); + // The |stream_codec_context| will be used during conversion and should be the + // AVCodecContext for the stream sourcing these packets. A reference to + // |stream_codec_context| is retained, so it must outlive this class. + explicit FFmpegAACBitstreamConverter(AVCodecContext* stream_codec_context); ~FFmpegAACBitstreamConverter() override; // FFmpegBitstreamConverter implementation. @@ -39,7 +38,7 @@ class MEDIA_EXPORT FFmpegAACBitstreamCon private: // Variable to hold a pointer to memory where we can access the global // data from the FFmpeg file format's global headers. - AVCodecParameters* stream_codec_parameters_; + AVCodecContext* stream_codec_context_; bool header_generated_; uint8_t hdr_[kAdtsHeaderSize]; diff -up chromium-60.0.3112.101/media/filters/ffmpeg_aac_bitstream_converter_unittest.cc.0108 chromium-60.0.3112.101/media/filters/ffmpeg_aac_bitstream_converter_unittest.cc --- chromium-60.0.3112.101/media/filters/ffmpeg_aac_bitstream_converter_unittest.cc.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/filters/ffmpeg_aac_bitstream_converter_unittest.cc 2017-08-26 16:09:40.810000000 +0200 @@ -23,15 +23,15 @@ class FFmpegAACBitstreamConverterTest : protected: FFmpegAACBitstreamConverterTest() { // Minimal extra data header - memset(extradata_header_, 0, sizeof(extradata_header_)); + memset(context_header_, 0, sizeof(context_header_)); - // Set up reasonable aac parameters - memset(&test_parameters_, 0, sizeof(AVCodecParameters)); - test_parameters_.codec_id = AV_CODEC_ID_AAC; - test_parameters_.profile = FF_PROFILE_AAC_MAIN; - test_parameters_.channels = 2; - test_parameters_.extradata = extradata_header_; - test_parameters_.extradata_size = sizeof(extradata_header_); + // Set up reasonable aac context + memset(&test_context_, 0, sizeof(AVCodecContext)); + test_context_.codec_id = AV_CODEC_ID_AAC; + test_context_.profile = FF_PROFILE_AAC_MAIN; + test_context_.channels = 2; + test_context_.extradata = context_header_; + test_context_.extradata_size = sizeof(context_header_); } void CreatePacket(AVPacket* packet, const uint8_t* data, uint32_t data_size) { @@ -40,17 +40,17 @@ class FFmpegAACBitstreamConverterTest : memcpy(packet->data, data, data_size); } - // Variable to hold valid dummy parameters for testing. - AVCodecParameters test_parameters_; + // Variable to hold valid dummy context for testing. + AVCodecContext test_context_; private: - uint8_t extradata_header_[2]; + uint8_t context_header_[2]; DISALLOW_COPY_AND_ASSIGN(FFmpegAACBitstreamConverterTest); }; TEST_F(FFmpegAACBitstreamConverterTest, Conversion_Success) { - FFmpegAACBitstreamConverter converter(&test_parameters_); + FFmpegAACBitstreamConverter converter(&test_context_); uint8_t dummy_packet[1000]; // Fill dummy packet with junk data. aac converter doesn't look into packet @@ -80,10 +80,10 @@ TEST_F(FFmpegAACBitstreamConverterTest, TEST_F(FFmpegAACBitstreamConverterTest, Conversion_FailureNullParams) { // Set up AVCConfigurationRecord to represent NULL data. - AVCodecParameters dummy_parameters; - dummy_parameters.extradata = nullptr; - dummy_parameters.extradata_size = 0; - FFmpegAACBitstreamConverter converter(&dummy_parameters); + AVCodecContext dummy_context; + dummy_context.extradata = NULL; + dummy_context.extradata_size = 0; + FFmpegAACBitstreamConverter converter(&dummy_context); uint8_t dummy_packet[1000] = {0}; @@ -99,7 +99,7 @@ TEST_F(FFmpegAACBitstreamConverterTest, } TEST_F(FFmpegAACBitstreamConverterTest, Conversion_AudioProfileType) { - FFmpegAACBitstreamConverter converter(&test_parameters_); + FFmpegAACBitstreamConverter converter(&test_context_); uint8_t dummy_packet[1000] = {0}; @@ -109,13 +109,13 @@ TEST_F(FFmpegAACBitstreamConverterTest, EXPECT_TRUE(converter.ConvertPacket(test_packet.get())); - // Check that the ADTS header profile matches the parameters + // Check that the ADTS header profile matches the context int profile = ((test_packet->data[2] & 0xC0) >> 6); EXPECT_EQ(profile, kAacMainProfile); - test_parameters_.profile = FF_PROFILE_AAC_HE; - FFmpegAACBitstreamConverter converter_he(&test_parameters_); + test_context_.profile = FF_PROFILE_AAC_HE; + FFmpegAACBitstreamConverter converter_he(&test_context_); test_packet.reset(new AVPacket()); CreatePacket(test_packet.get(), dummy_packet, @@ -127,8 +127,8 @@ TEST_F(FFmpegAACBitstreamConverterTest, EXPECT_EQ(profile, kAacLowComplexityProfile); - test_parameters_.profile = FF_PROFILE_AAC_ELD; - FFmpegAACBitstreamConverter converter_eld(&test_parameters_); + test_context_.profile = FF_PROFILE_AAC_ELD; + FFmpegAACBitstreamConverter converter_eld(&test_context_); test_packet.reset(new AVPacket()); CreatePacket(test_packet.get(), dummy_packet, @@ -138,7 +138,7 @@ TEST_F(FFmpegAACBitstreamConverterTest, } TEST_F(FFmpegAACBitstreamConverterTest, Conversion_MultipleLength) { - FFmpegAACBitstreamConverter converter(&test_parameters_); + FFmpegAACBitstreamConverter converter(&test_context_); uint8_t dummy_packet[1000]; diff -up chromium-60.0.3112.101/media/filters/ffmpeg_demuxer.cc.0108 chromium-60.0.3112.101/media/filters/ffmpeg_demuxer.cc --- chromium-60.0.3112.101/media/filters/ffmpeg_demuxer.cc.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/filters/ffmpeg_demuxer.cc 2017-08-26 16:22:13.590000000 +0200 @@ -67,10 +67,8 @@ static base::Time ExtractTimelineOffset( 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 && - base::Time::FromUTCString(entry->value, &timeline_offset)) { + FFmpegUTCDateToTime(entry->value, &timeline_offset)) { return timeline_offset; } } @@ -204,8 +202,11 @@ static void RecordVideoCodecStats(contai static const char kCodecNone[] = "none"; -static const char* GetCodecName(enum AVCodecID id) { - const AVCodecDescriptor* codec_descriptor = avcodec_descriptor_get(id); +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); // If the codec name can't be determined, return none for tracking. return codec_descriptor ? codec_descriptor->name : kCodecNone; } @@ -232,7 +233,7 @@ std::unique_ptr<FFmpegDemuxerStream> FFm std::unique_ptr<AudioDecoderConfig> audio_config; std::unique_ptr<VideoDecoderConfig> video_config; - if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + if (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO) { audio_config.reset(new AudioDecoderConfig()); // IsValidConfig() checks that the codec is supported and that the channel @@ -249,7 +250,7 @@ std::unique_ptr<FFmpegDemuxerStream> FFm MEDIA_LOG(INFO, media_log) << "FFmpegDemuxer: created audio stream, config " << audio_config->AsHumanReadableString(); - } else if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + } 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 @@ -311,7 +312,7 @@ FFmpegDemuxerStream::FFmpegDemuxerStream AVDictionaryEntry* rotation_entry = NULL; // Determine our media format. - switch (stream->codecpar->codec_type) { + switch (stream->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: DCHECK(audio_config_.get() && !video_config_.get()); type_ = AUDIO; @@ -542,7 +543,7 @@ void FFmpegDemuxerStream::EnqueuePacket( if (fixup_negative_timestamps_ && is_audio && stream_timestamp < base::TimeDelta() && buffer->duration() != kNoTimestamp && - !audio_decoder_config().codec_delay()) { + !stream_->codec->delay) { DCHECK_EQ(buffer->discard_padding().first, base::TimeDelta()); if (stream_timestamp + buffer->duration() < base::TimeDelta()) { @@ -700,7 +701,7 @@ void FFmpegDemuxerStream::ResetBitstream void FFmpegDemuxerStream::InitBitstreamConverter() { #if BUILDFLAG(USE_PROPRIETARY_CODECS) - switch (stream_->codecpar->codec_id) { + switch (stream_->codec->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. @@ -712,17 +713,17 @@ void FFmpegDemuxerStream::InitBitstreamC if (video_config_) video_config_->SetExtraData(std::vector<uint8_t>()); bitstream_converter_.reset( - new FFmpegH264ToAnnexBBitstreamConverter(stream_->codecpar)); + new FFmpegH264ToAnnexBBitstreamConverter(stream_->codec)); break; #if BUILDFLAG(ENABLE_HEVC_DEMUXING) case AV_CODEC_ID_HEVC: bitstream_converter_.reset( - new FFmpegH265ToAnnexBBitstreamConverter(stream_->codecpar)); + new FFmpegH265ToAnnexBBitstreamConverter(stream_->codec)); break; #endif case AV_CODEC_ID_AAC: bitstream_converter_.reset( - new FFmpegAACBitstreamConverter(stream_->codecpar)); + new FFmpegAACBitstreamConverter(stream_->codec)); break; default: break; @@ -1171,8 +1172,8 @@ static int CalculateBitrate(AVFormatCont // Then try to sum the bitrates individually per stream. int bitrate = 0; for (size_t i = 0; i < format_context->nb_streams; ++i) { - AVCodecParameters* codec_parameters = format_context->streams[i]->codecpar; - bitrate += codec_parameters->bit_rate; + AVCodecContext* codec_context = format_context->streams[i]->codec; + bitrate += codec_context->bit_rate; } if (bitrate > 0) return bitrate; @@ -1287,40 +1288,46 @@ void FFmpegDemuxer::OnFindStreamInfoDone int detected_text_track_count = 0; for (size_t i = 0; i < format_context->nb_streams; ++i) { AVStream* stream = format_context->streams[i]; - const AVCodecParameters* codec_parameters = stream->codecpar; - const AVMediaType codec_type = codec_parameters->codec_type; - const AVCodecID codec_id = codec_parameters->codec_id; + const AVCodecContext* codec_context = stream->codec; + const AVMediaType codec_type = codec_context->codec_type; 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_id))); + HashCodecName(GetCodecName(codec_context))); 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_id))); + HashCodecName(GetCodecName(codec_context))); detected_video_track_count++; #if BUILDFLAG(ENABLE_HEVC_DEMUXING) - if (codec_id == AV_CODEC_ID_HEVC) { + if (stream->codec->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 - // 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; + // 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; + } } #endif } else if (codec_type == AVMEDIA_TYPE_SUBTITLE) { detected_text_track_count++; - if (codec_id != AV_CODEC_ID_WEBVTT || !text_enabled_) { + if (codec_context->codec_id != AV_CODEC_ID_WEBVTT || !text_enabled_) { stream->discard = AVDISCARD_ALL; continue; } @@ -1352,6 +1359,7 @@ void FFmpegDemuxer::OnFindStreamInfoDone } StreamParser::TrackId track_id = stream->id; + std::string track_label = streams_[i]->GetMetadata("handler_name"); std::string track_language = streams_[i]->GetMetadata("language"); @@ -1399,7 +1407,7 @@ void FFmpegDemuxer::OnFindStreamInfoDone VideoDecoderConfig video_config = streams_[i]->video_decoder_config(); RecordVideoCodecStats(glue_->container(), video_config, - stream->codecpar->color_range, media_log_); + stream->codec->color_range, media_log_); media_track = media_tracks->AddVideoTrack(video_config, track_id, "main", track_label, track_language); @@ -1466,9 +1474,9 @@ void FFmpegDemuxer::OnFindStreamInfoDone continue; const AVStream* audio_stream = stream->av_stream(); DCHECK(audio_stream); - if (audio_stream->codecpar->codec_id == AV_CODEC_ID_OPUS || + if (audio_stream->codec->codec_id == AV_CODEC_ID_OPUS || (glue_->container() == container_names::CONTAINER_OGG && - audio_stream->codecpar->codec_id == AV_CODEC_ID_VORBIS)) { + audio_stream->codec->codec_id == AV_CODEC_ID_VORBIS)) { for (size_t i = 0; i < streams_.size(); ++i) { if (!streams_[i]) continue; @@ -1551,12 +1559,10 @@ void FFmpegDemuxer::LogMetadata(AVFormat std::string suffix = ""; if (audio_track_count > 1) suffix = "_track" + base::IntToString(audio_track_count); - const AVCodecParameters* audio_parameters = avctx->streams[i]->codecpar; + const AVCodecContext* audio_codec = avctx->streams[i]->codec; const AudioDecoderConfig& audio_config = stream->audio_decoder_config(); - params.SetString("audio_codec_name" + suffix, - GetCodecName(audio_parameters->codec_id)); - params.SetInteger("audio_channels_count" + suffix, - audio_parameters->channels); + params.SetString("audio_codec_name" + suffix, GetCodecName(audio_codec)); + params.SetInteger("audio_channels_count" + suffix, audio_codec->channels); params.SetString("audio_sample_format" + suffix, SampleFormatToString(audio_config.sample_format())); params.SetInteger("audio_samples_per_second" + suffix, @@ -1566,21 +1572,14 @@ void FFmpegDemuxer::LogMetadata(AVFormat std::string suffix = ""; if (video_track_count > 1) suffix = "_track" + base::IntToString(video_track_count); - const AVStream* video_av_stream = avctx->streams[i]; - const AVCodecParameters* video_parameters = video_av_stream->codecpar; + const AVCodecContext* video_codec = avctx->streams[i]->codec; const VideoDecoderConfig& video_config = stream->video_decoder_config(); - 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_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_format" + suffix, VideoPixelFormatToString(video_config.format())); params.SetBoolean("video_is_encrypted" + suffix, diff -up chromium-60.0.3112.101/media/filters/ffmpeg_demuxer_unittest.cc.0108 chromium-60.0.3112.101/media/filters/ffmpeg_demuxer_unittest.cc --- chromium-60.0.3112.101/media/filters/ffmpeg_demuxer_unittest.cc.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/filters/ffmpeg_demuxer_unittest.cc 2017-08-26 16:09:40.810000000 +0200 @@ -1528,56 +1528,6 @@ TEST_F(FFmpegDemuxerTest, Read_Webm_Medi EXPECT_EQ(audio_track.language(), ""); } -// UTCDateToTime_* tests here assume FFmpegDemuxer's ExtractTimelineOffset -// helper uses base::Time::FromUTCString() for conversion. -TEST_F(FFmpegDemuxerTest, UTCDateToTime_Valid) { - base::Time result; - EXPECT_TRUE( - base::Time::FromUTCString("2012-11-10T12:34:56.987654Z", &result)); - - base::Time::Exploded exploded; - result.UTCExplode(&exploded); - EXPECT_TRUE(exploded.HasValidValues()); - EXPECT_EQ(2012, exploded.year); - EXPECT_EQ(11, exploded.month); - EXPECT_EQ(6, exploded.day_of_week); - EXPECT_EQ(10, exploded.day_of_month); - EXPECT_EQ(12, exploded.hour); - EXPECT_EQ(34, exploded.minute); - EXPECT_EQ(56, exploded.second); - EXPECT_EQ(987, exploded.millisecond); - - // base::Time exploding operations round fractional milliseconds down, so - // verify fractional milliseconds using a base::TimeDelta. - base::Time without_fractional_ms; - EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &without_fractional_ms)); - base::TimeDelta delta = result - without_fractional_ms; - EXPECT_EQ(654, delta.InMicroseconds()); -} - -TEST_F(FFmpegDemuxerTest, UTCDateToTime_Invalid) { - const char* invalid_date_strings[] = { - "", - "12:34:56", - "-- ::", - "2012-11- 12:34:56", - "2012--10 12:34:56", - "-11-10 12:34:56", - "2012-11 12:34:56", - "ABCD-11-10 12:34:56", - "2012-EF-10 12:34:56", - "2012-11-GH 12:34:56", - "2012-11-1012:34:56", - }; - - for (size_t i = 0; i < arraysize(invalid_date_strings); ++i) { - const char* date_string = invalid_date_strings[i]; - base::Time result; - EXPECT_FALSE(base::Time::FromUTCString(date_string, &result)) - << "date_string '" << date_string << "'"; - } -} - TEST_F(FFmpegDemuxerTest, Read_Flac) { CreateDemuxer("sfx.flac"); InitializeDemuxer(); diff -up chromium-60.0.3112.101/media/filters/ffmpeg_glue.cc.0108 chromium-60.0.3112.101/media/filters/ffmpeg_glue.cc --- chromium-60.0.3112.101/media/filters/ffmpeg_glue.cc.0108 2017-08-26 16:09:40.710000000 +0200 +++ chromium-60.0.3112.101/media/filters/ffmpeg_glue.cc 2017-08-26 16:09:40.810000000 +0200 @@ -213,6 +213,26 @@ FFmpegGlue::~FFmpegGlue() { return; } + // If avformat_open_input() has been called with this context, we need to + // close out any codecs/streams before closing the context. + if (format_context_->streams) { + for (int i = format_context_->nb_streams - 1; i >= 0; --i) { + AVStream* stream = format_context_->streams[i]; + + // The conditions for calling avcodec_close(): + // 1. AVStream is alive. + // 2. AVCodecContext in AVStream is alive. + // 3. AVCodec in AVCodecContext is alive. + // + // Closing a codec context without prior avcodec_open2() will result in + // a crash in FFmpeg. + if (stream && stream->codec && stream->codec->codec) { + stream->discard = AVDISCARD_ALL; + avcodec_close(stream->codec); + } + } + } + avformat_close_input(&format_context_); av_free(avio_context_->buffer); } diff -up chromium-60.0.3112.101/media/filters/ffmpeg_glue_unittest.cc.0108 chromium-60.0.3112.101/media/filters/ffmpeg_glue_unittest.cc --- chromium-60.0.3112.101/media/filters/ffmpeg_glue_unittest.cc.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/filters/ffmpeg_glue_unittest.cc 2017-08-26 16:23:52.980000000 +0200 @@ -15,7 +15,6 @@ #include "media/base/mock_filters.h" #include "media/base/test_data_util.h" #include "media/ffmpeg/ffmpeg_common.h" -#include "media/ffmpeg/ffmpeg_deleters.h" #include "media/filters/in_memory_url_protocol.h" #include "testing/gtest/include/gtest/gtest.h" @@ -260,22 +259,17 @@ TEST_F(FFmpegGlueDestructionTest, WithOp } // Ensure destruction release the appropriate resources when OpenContext() is -// called and streams have been opened. This now requires user of FFmpegGlue to -// ensure any allocated AVCodecContext is closed prior to ~FFmpegGlue(). +// called and streams have been opened. TEST_F(FFmpegGlueDestructionTest, WithOpenWithOpenStreams) { Initialize("bear-320x240.webm"); ASSERT_TRUE(glue_->OpenContext()); ASSERT_GT(glue_->format_context()->nb_streams, 0u); - // Use ScopedPtrAVFreeContext to ensure |context| is closed, and use scoping - // and ordering to ensure |context| is destructed before |glue_|. // Pick the audio stream (1) so this works when the ffmpeg video decoders are // disabled. - std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> context( - AVStreamToAVCodecContext(glue_->format_context()->streams[1])); - ASSERT_NE(nullptr, context.get()); - ASSERT_EQ(0, avcodec_open2(context.get(), - avcodec_find_decoder(context->codec_id), nullptr)); + AVCodecContext* context = glue_->format_context()->streams[1]->codec; + ASSERT_EQ(0, avcodec_open2( + context, avcodec_find_decoder(context->codec_id), NULL)); } TEST_F(FFmpegGlueContainerTest, OGG) { diff -up chromium-60.0.3112.101/media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.cc.0108 chromium-60.0.3112.101/media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.cc --- chromium-60.0.3112.101/media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.cc.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.cc 2017-08-26 16:09:40.810000000 +0200 @@ -13,10 +13,10 @@ namespace media { FFmpegH264ToAnnexBBitstreamConverter::FFmpegH264ToAnnexBBitstreamConverter( - AVCodecParameters* stream_codec_parameters) + AVCodecContext* stream_codec_context) : configuration_processed_(false), - stream_codec_parameters_(stream_codec_parameters) { - CHECK(stream_codec_parameters_); + stream_codec_context_(stream_codec_context) { + CHECK(stream_codec_context_); } FFmpegH264ToAnnexBBitstreamConverter::~FFmpegH264ToAnnexBBitstreamConverter() {} @@ -29,15 +29,16 @@ bool FFmpegH264ToAnnexBBitstreamConverte // Calculate the needed output buffer size. if (!configuration_processed_) { - if (!stream_codec_parameters_->extradata || - stream_codec_parameters_->extradata_size <= 0) + if (!stream_codec_context_->extradata || + stream_codec_context_->extradata_size <= 0) return false; avc_config.reset(new mp4::AVCDecoderConfigurationRecord()); - if (!converter_.ParseConfiguration(stream_codec_parameters_->extradata, - stream_codec_parameters_->extradata_size, - avc_config.get())) { + if (!converter_.ParseConfiguration( + stream_codec_context_->extradata, + stream_codec_context_->extradata_size, + avc_config.get())) { return false; } } diff -up chromium-60.0.3112.101/media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.h.0108 chromium-60.0.3112.101/media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.h --- chromium-60.0.3112.101/media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.h.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.h 2017-08-26 16:09:40.810000000 +0200 @@ -11,7 +11,7 @@ #include "media/filters/h264_to_annex_b_bitstream_converter.h" // Forward declarations for FFmpeg datatypes used. -struct AVCodecParameters; +struct AVCodecContext; struct AVPacket; namespace media { @@ -21,11 +21,11 @@ namespace media { class MEDIA_EXPORT FFmpegH264ToAnnexBBitstreamConverter : public FFmpegBitstreamConverter { public: - // The |stream_codec_parameters| will be used during conversion and should be - // the AVCodecParameters for the stream sourcing these packets. A reference to - // |stream_codec_parameters| is retained, so it must outlive this class. + // The |stream_codec_context| will be used during conversion and should be the + // AVCodecContext for the stream sourcing these packets. A reference to + // |stream_codec_context| is retained, so it must outlive this class. explicit FFmpegH264ToAnnexBBitstreamConverter( - AVCodecParameters* stream_codec_parameters); + AVCodecContext* stream_codec_context); ~FFmpegH264ToAnnexBBitstreamConverter() override; @@ -59,7 +59,7 @@ class MEDIA_EXPORT FFmpegH264ToAnnexBBit // Variable to hold a pointer to memory where we can access the global // data from the FFmpeg file format's global headers. - AVCodecParameters* stream_codec_parameters_; + AVCodecContext* stream_codec_context_; DISALLOW_COPY_AND_ASSIGN(FFmpegH264ToAnnexBBitstreamConverter); }; diff -up chromium-60.0.3112.101/media/filters/ffmpeg_h264_to_annex_b_bitstream_converter_unittest.cc.0108 chromium-60.0.3112.101/media/filters/ffmpeg_h264_to_annex_b_bitstream_converter_unittest.cc --- chromium-60.0.3112.101/media/filters/ffmpeg_h264_to_annex_b_bitstream_converter_unittest.cc.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/filters/ffmpeg_h264_to_annex_b_bitstream_converter_unittest.cc 2017-08-26 16:09:40.810000000 +0200 @@ -282,10 +282,9 @@ class FFmpegH264ToAnnexBBitstreamConvert // Set up AVCConfigurationRecord correctly for tests. // It's ok to do const cast here as data in kHeaderDataOkWithFieldLen4 is // never written to. - memset(&test_parameters_, 0, sizeof(AVCodecParameters)); - test_parameters_.extradata = - const_cast<uint8_t*>(kHeaderDataOkWithFieldLen4); - test_parameters_.extradata_size = sizeof(kHeaderDataOkWithFieldLen4); + memset(&test_context_, 0, sizeof(AVCodecContext)); + test_context_.extradata = const_cast<uint8_t*>(kHeaderDataOkWithFieldLen4); + test_context_.extradata_size = sizeof(kHeaderDataOkWithFieldLen4); } void CreatePacket(AVPacket* packet, const uint8_t* data, uint32_t data_size) { @@ -294,15 +293,15 @@ class FFmpegH264ToAnnexBBitstreamConvert memcpy(packet->data, data, data_size); } - // Variable to hold valid dummy parameters for testing. - AVCodecParameters test_parameters_; + // Variable to hold valid dummy context for testing. + AVCodecContext test_context_; private: DISALLOW_COPY_AND_ASSIGN(FFmpegH264ToAnnexBBitstreamConverterTest); }; TEST_F(FFmpegH264ToAnnexBBitstreamConverterTest, Conversion_Success) { - FFmpegH264ToAnnexBBitstreamConverter converter(&test_parameters_); + FFmpegH264ToAnnexBBitstreamConverter converter(&test_context_); ScopedAVPacket test_packet(new AVPacket()); CreatePacket(test_packet.get(), kPacketDataOkWithFieldLen4, @@ -316,7 +315,7 @@ TEST_F(FFmpegH264ToAnnexBBitstreamConver } TEST_F(FFmpegH264ToAnnexBBitstreamConverterTest, Conversion_SuccessBigPacket) { - FFmpegH264ToAnnexBBitstreamConverter converter(&test_parameters_); + FFmpegH264ToAnnexBBitstreamConverter converter(&test_context_); // Create new packet with 1000 excess bytes. ScopedAVPacket test_packet(new AVPacket()); @@ -334,13 +333,13 @@ TEST_F(FFmpegH264ToAnnexBBitstreamConver TEST_F(FFmpegH264ToAnnexBBitstreamConverterTest, Conversion_FailureNullParams) { // Set up AVCConfigurationRecord to represent NULL data. - AVCodecParameters dummy_parameters; - dummy_parameters.extradata = nullptr; - dummy_parameters.extradata_size = 0; - FFmpegH264ToAnnexBBitstreamConverter converter(&dummy_parameters); + AVCodecContext dummy_context; + dummy_context.extradata = NULL; + dummy_context.extradata_size = 0; + FFmpegH264ToAnnexBBitstreamConverter converter(&dummy_context); // Try out the actual conversion with NULL parameter. - EXPECT_FALSE(converter.ConvertPacket(nullptr)); + EXPECT_FALSE(converter.ConvertPacket(NULL)); // Create new packet to test actual conversion. ScopedAVPacket test_packet(new AVPacket()); @@ -350,7 +349,7 @@ TEST_F(FFmpegH264ToAnnexBBitstreamConver // Try out the actual conversion. This should fail due to missing extradata. EXPECT_FALSE(converter.ConvertPacket(test_packet.get())); - // Converter will be automatically cleaned up. + // Converted will be automatically cleaned up. } } // namespace media diff -up chromium-60.0.3112.101/media/filters/ffmpeg_h265_to_annex_b_bitstream_converter.cc.0108 chromium-60.0.3112.101/media/filters/ffmpeg_h265_to_annex_b_bitstream_converter.cc --- chromium-60.0.3112.101/media/filters/ffmpeg_h265_to_annex_b_bitstream_converter.cc.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/filters/ffmpeg_h265_to_annex_b_bitstream_converter.cc 2017-08-26 16:09:40.810000000 +0200 @@ -16,9 +16,9 @@ namespace media { FFmpegH265ToAnnexBBitstreamConverter::FFmpegH265ToAnnexBBitstreamConverter( - AVCodecParameters* stream_codec_parameters) - : stream_codec_parameters_(stream_codec_parameters) { - CHECK(stream_codec_parameters_); + AVCodecContext* stream_codec_context) + : stream_codec_context_(stream_codec_context) { + CHECK(stream_codec_context_); } FFmpegH265ToAnnexBBitstreamConverter::~FFmpegH265ToAnnexBBitstreamConverter() {} @@ -30,16 +30,17 @@ bool FFmpegH265ToAnnexBBitstreamConverte // Calculate the needed output buffer size. if (!hevc_config_) { - if (!stream_codec_parameters_->extradata || - stream_codec_parameters_->extradata_size <= 0) { + if (!stream_codec_context_->extradata || + stream_codec_context_->extradata_size <= 0) { DVLOG(1) << "HEVCDecoderConfiguration not found, no extra codec data"; return false; } hevc_config_.reset(new mp4::HEVCDecoderConfigurationRecord()); - if (!hevc_config_->Parse(stream_codec_parameters_->extradata, - stream_codec_parameters_->extradata_size)) { + if (!hevc_config_->Parse( + stream_codec_context_->extradata, + stream_codec_context_->extradata_size)) { DVLOG(1) << "Parsing HEVCDecoderConfiguration failed"; return false; } diff -up chromium-60.0.3112.101/media/filters/ffmpeg_h265_to_annex_b_bitstream_converter.h.0108 chromium-60.0.3112.101/media/filters/ffmpeg_h265_to_annex_b_bitstream_converter.h --- chromium-60.0.3112.101/media/filters/ffmpeg_h265_to_annex_b_bitstream_converter.h.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/filters/ffmpeg_h265_to_annex_b_bitstream_converter.h 2017-08-26 16:09:40.810000000 +0200 @@ -13,7 +13,7 @@ #include "media/formats/mp4/hevc.h" // Forward declarations for FFmpeg datatypes used. -struct AVCodecParameters; +struct AVCodecContext; struct AVPacket; namespace media { @@ -23,11 +23,11 @@ namespace media { class MEDIA_EXPORT FFmpegH265ToAnnexBBitstreamConverter : public FFmpegBitstreamConverter { public: - // The |stream_codec_parameters| will be used during conversion and should be - // the AVCodecParameters for the stream sourcing these packets. A reference to - // |stream_codec_parameters| is retained, so it must outlive this class. + // The |stream_codec_context| will be used during conversion and should be the + // AVCodecContext for the stream sourcing these packets. A reference to + // |stream_codec_context| is retained, so it must outlive this class. explicit FFmpegH265ToAnnexBBitstreamConverter( - AVCodecParameters* stream_codec_parameters); + AVCodecContext* stream_codec_context); ~FFmpegH265ToAnnexBBitstreamConverter() override; @@ -39,7 +39,7 @@ class MEDIA_EXPORT FFmpegH265ToAnnexBBit // Variable to hold a pointer to memory where we can access the global // data from the FFmpeg file format's global headers. - AVCodecParameters* stream_codec_parameters_; + AVCodecContext* stream_codec_context_; DISALLOW_COPY_AND_ASSIGN(FFmpegH265ToAnnexBBitstreamConverter); }; diff -up chromium-60.0.3112.101/media/test/pipeline_integration_test.cc.0108 chromium-60.0.3112.101/media/test/pipeline_integration_test.cc --- chromium-60.0.3112.101/media/test/pipeline_integration_test.cc.0108 2017-08-14 21:05:09.000000000 +0200 +++ chromium-60.0.3112.101/media/test/pipeline_integration_test.cc 2017-08-26 16:24:38.850000000 +0200 @@ -183,6 +183,17 @@ static base::Time kLiveTimelineOffset() return timeline_offset; } +// FFmpeg only supports time a resolution of seconds so this +// helper function truncates a base::Time to seconds resolution. +static base::Time TruncateToFFmpegTimeResolution(base::Time t) { + base::Time::Exploded exploded_time; + t.UTCExplode(&exploded_time); + exploded_time.millisecond = 0; + base::Time out_time; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded_time, &out_time)); + return out_time; +} + enum PromiseResult { RESOLVED, REJECTED }; // Provides the test key in response to the encrypted event. @@ -961,7 +972,11 @@ TEST_F(PipelineIntegrationTest, BasicPla EXPECT_HASH_EQ("f0be120a90a811506777c99a2cdf7cc1", GetVideoHash()); EXPECT_HASH_EQ("-3.59,-2.06,-0.43,2.15,0.77,-0.95,", GetAudioHash()); - EXPECT_EQ(kLiveTimelineOffset(), demuxer_->GetTimelineOffset()); + + // TODO: Fix FFmpeg code to return higher resolution time values so + // we don't have to truncate our expectations here. + EXPECT_EQ(TruncateToFFmpegTimeResolution(kLiveTimelineOffset()), + demuxer_->GetTimelineOffset()); } TEST_F(PipelineIntegrationTest, S32PlaybackHashed) {