| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // ffmpeg_unittests verify that the parts of the FFmpeg API that Chromium uses | 5 // ffmpeg_unittests verify that the parts of the FFmpeg API that Chromium uses |
| 6 // function as advertised for each media format that Chromium supports. This | 6 // function as advertised for each media format that Chromium supports. This |
| 7 // mostly includes stuff like reporting proper timestamps, seeking to | 7 // mostly includes stuff like reporting proper timestamps, seeking to |
| 8 // keyframes, and supporting certain features like reordered_opaque. | 8 // keyframes, and supporting certain features like reordered_opaque. |
| 9 // | 9 // |
| 10 // Known failures as of r54591: | 10 // Known failures as of r54591: |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 #include "media/ffmpeg/ffmpeg_common.h" | 39 #include "media/ffmpeg/ffmpeg_common.h" |
| 40 #include "media/ffmpeg/file_protocol.h" | 40 #include "media/ffmpeg/file_protocol.h" |
| 41 #include "testing/gtest/include/gtest/gtest.h" | 41 #include "testing/gtest/include/gtest/gtest.h" |
| 42 | 42 |
| 43 int main(int argc, char** argv) { | 43 int main(int argc, char** argv) { |
| 44 return base::PerfTestSuite(argc, argv).Run(); | 44 return base::PerfTestSuite(argc, argv).Run(); |
| 45 } | 45 } |
| 46 | 46 |
| 47 namespace media { | 47 namespace media { |
| 48 | 48 |
| 49 // Mirror setting in ffmpeg_video_decoder. |
| 50 static const int kDecodeThreads = 2; |
| 51 |
| 49 class AVPacketQueue { | 52 class AVPacketQueue { |
| 50 public: | 53 public: |
| 51 AVPacketQueue() { | 54 AVPacketQueue() { |
| 52 } | 55 } |
| 53 | 56 |
| 54 ~AVPacketQueue() { | 57 ~AVPacketQueue() { |
| 55 flush(); | 58 flush(); |
| 56 } | 59 } |
| 57 | 60 |
| 58 bool empty() { | 61 bool empty() { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 80 pop(); | 83 pop(); |
| 81 } | 84 } |
| 82 } | 85 } |
| 83 | 86 |
| 84 private: | 87 private: |
| 85 std::queue<AVPacket*> packets_; | 88 std::queue<AVPacket*> packets_; |
| 86 | 89 |
| 87 DISALLOW_COPY_AND_ASSIGN(AVPacketQueue); | 90 DISALLOW_COPY_AND_ASSIGN(AVPacketQueue); |
| 88 }; | 91 }; |
| 89 | 92 |
| 93 // TODO(dalecurtis): We should really just use PipelineIntegrationTests instead |
| 94 // of a one-off step decoder so we're exercising the real pipeline. |
| 90 class FFmpegTest : public testing::TestWithParam<const char*> { | 95 class FFmpegTest : public testing::TestWithParam<const char*> { |
| 91 protected: | 96 protected: |
| 92 FFmpegTest() | 97 FFmpegTest() |
| 93 : av_format_context_(NULL), | 98 : av_format_context_(NULL), |
| 94 audio_stream_index_(-1), | 99 audio_stream_index_(-1), |
| 95 video_stream_index_(-1), | 100 video_stream_index_(-1), |
| 96 audio_buffer_(NULL), | 101 audio_buffer_(NULL), |
| 97 video_buffer_(NULL), | 102 video_buffer_(NULL), |
| 98 decoded_audio_time_(AV_NOPTS_VALUE), | 103 decoded_audio_time_(AV_NOPTS_VALUE), |
| 99 decoded_audio_duration_(AV_NOPTS_VALUE), | 104 decoded_audio_duration_(AV_NOPTS_VALUE), |
| (...skipping 26 matching lines...) Expand all Loading... |
| 126 .AppendASCII(name.c_str()); | 131 .AppendASCII(name.c_str()); |
| 127 FilePath::StringType raw_path = path.value(); | 132 FilePath::StringType raw_path = path.value(); |
| 128 EXPECT_TRUE(file_util::PathExists(path)); | 133 EXPECT_TRUE(file_util::PathExists(path)); |
| 129 | 134 |
| 130 #if defined(OS_WIN) | 135 #if defined(OS_WIN) |
| 131 std::string ascii_path = WideToASCII(path.value()); | 136 std::string ascii_path = WideToASCII(path.value()); |
| 132 #else | 137 #else |
| 133 std::string ascii_path = path.value(); | 138 std::string ascii_path = path.value(); |
| 134 #endif | 139 #endif |
| 135 | 140 |
| 136 EXPECT_EQ(0, av_open_input_file(&av_format_context_, | 141 EXPECT_EQ(0, avformat_open_input(&av_format_context_, |
| 137 ascii_path.c_str(), | 142 ascii_path.c_str(), |
| 138 NULL, 0, NULL)) | 143 NULL, NULL)) |
| 139 << "Could not open " << path.value(); | 144 << "Could not open " << path.value(); |
| 140 EXPECT_LE(0, av_find_stream_info(av_format_context_)) | 145 EXPECT_LE(0, avformat_find_stream_info(av_format_context_, NULL)) |
| 141 << "Could not find stream information for " << path.value(); | 146 << "Could not find stream information for " << path.value(); |
| 142 | 147 |
| 143 // Determine duration by picking max stream duration. | 148 // Determine duration by picking max stream duration. |
| 144 for (unsigned int i = 0; i < av_format_context_->nb_streams; ++i) { | 149 for (unsigned int i = 0; i < av_format_context_->nb_streams; ++i) { |
| 145 AVStream* av_stream = av_format_context_->streams[i]; | 150 AVStream* av_stream = av_format_context_->streams[i]; |
| 146 int64 duration = ConvertFromTimeBase(av_stream->time_base, | 151 int64 duration = ConvertFromTimeBase( |
| 147 av_stream->duration).InMicroseconds(); | 152 av_stream->time_base, av_stream->duration).InMicroseconds(); |
| 148 duration_ = std::max(duration_, duration); | 153 duration_ = std::max(duration_, duration); |
| 149 } | 154 } |
| 150 | 155 |
| 151 // Final check to see if the container itself specifies a duration. | 156 // Final check to see if the container itself specifies a duration. |
| 152 AVRational av_time_base = {1, AV_TIME_BASE}; | 157 AVRational av_time_base = {1, AV_TIME_BASE}; |
| 153 int64 duration = | 158 int64 duration = |
| 154 ConvertFromTimeBase(av_time_base, | 159 ConvertFromTimeBase(av_time_base, |
| 155 av_format_context_->duration).InMicroseconds(); | 160 av_format_context_->duration).InMicroseconds(); |
| 156 duration_ = std::max(duration_, duration); | 161 duration_ = std::max(duration_, duration); |
| 157 } | 162 } |
| 158 | 163 |
| 159 void CloseFile() { | 164 void CloseFile() { |
| 160 av_close_input_file(av_format_context_); | 165 avformat_close_input(&av_format_context_); |
| 161 } | 166 } |
| 162 | 167 |
| 163 void OpenCodecs() { | 168 void OpenCodecs() { |
| 164 for (unsigned int i = 0; i < av_format_context_->nb_streams; ++i) { | 169 for (unsigned int i = 0; i < av_format_context_->nb_streams; ++i) { |
| 165 AVStream* av_stream = av_format_context_->streams[i]; | 170 AVStream* av_stream = av_format_context_->streams[i]; |
| 166 AVCodecContext* av_codec_context = av_stream->codec; | 171 AVCodecContext* av_codec_context = av_stream->codec; |
| 167 AVCodec* av_codec = avcodec_find_decoder(av_codec_context->codec_id); | 172 AVCodec* av_codec = avcodec_find_decoder(av_codec_context->codec_id); |
| 168 | 173 |
| 169 EXPECT_TRUE(av_codec) | 174 EXPECT_TRUE(av_codec) |
| 170 << "Could not find AVCodec with CodecID " | 175 << "Could not find AVCodec with CodecID " |
| 171 << av_codec_context->codec_id; | 176 << av_codec_context->codec_id; |
| 172 EXPECT_EQ(0, avcodec_open(av_codec_context, av_codec)) | 177 |
| 178 av_codec_context->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK; |
| 179 av_codec_context->err_recognition = AV_EF_CAREFUL; |
| 180 av_codec_context->thread_count = ( |
| 181 av_codec_context->codec_id == CODEC_ID_THEORA ? 1 : kDecodeThreads); |
| 182 |
| 183 EXPECT_EQ(0, avcodec_open2(av_codec_context, av_codec, NULL)) |
| 173 << "Could not open AVCodecContext with CodecID " | 184 << "Could not open AVCodecContext with CodecID " |
| 174 << av_codec_context->codec_id; | 185 << av_codec_context->codec_id; |
| 175 | 186 |
| 176 if (av_codec->type == AVMEDIA_TYPE_AUDIO) { | 187 if (av_codec->type == AVMEDIA_TYPE_AUDIO) { |
| 177 EXPECT_EQ(-1, audio_stream_index_) << "Found multiple audio streams."; | 188 EXPECT_EQ(-1, audio_stream_index_) << "Found multiple audio streams."; |
| 178 audio_stream_index_ = static_cast<int>(i); | 189 audio_stream_index_ = static_cast<int>(i); |
| 179 } else if (av_codec->type == AVMEDIA_TYPE_VIDEO) { | 190 } else if (av_codec->type == AVMEDIA_TYPE_VIDEO) { |
| 180 EXPECT_EQ(-1, video_stream_index_) << "Found multiple video streams."; | 191 EXPECT_EQ(-1, video_stream_index_) << "Found multiple video streams."; |
| 181 video_stream_index_ = static_cast<int>(i); | 192 video_stream_index_ = static_cast<int>(i); |
| 182 } else { | 193 } else { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 } | 275 } |
| 265 | 276 |
| 266 EXPECT_GE(result, 0) << "Audio decode error."; | 277 EXPECT_GE(result, 0) << "Audio decode error."; |
| 267 if (result < 0 || (size_out == 0 && end_of_stream)) { | 278 if (result < 0 || (size_out == 0 && end_of_stream)) { |
| 268 return false; | 279 return false; |
| 269 } | 280 } |
| 270 | 281 |
| 271 if (result > 0) { | 282 if (result > 0) { |
| 272 // TODO(scherkus): move this to ffmpeg_common.h and dedup. | 283 // TODO(scherkus): move this to ffmpeg_common.h and dedup. |
| 273 int64 denominator = av_audio_context()->channels * | 284 int64 denominator = av_audio_context()->channels * |
| 274 av_get_bits_per_sample_fmt(av_audio_context()->sample_fmt) / 8 * | 285 av_get_bytes_per_sample(av_audio_context()->sample_fmt) * |
| 275 av_audio_context()->sample_rate; | 286 av_audio_context()->sample_rate; |
| 276 double microseconds = size_out / | 287 double microseconds = size_out / |
| 277 (denominator / | 288 (denominator / |
| 278 static_cast<double>(base::Time::kMicrosecondsPerSecond)); | 289 static_cast<double>(base::Time::kMicrosecondsPerSecond)); |
| 279 decoded_audio_duration_ = static_cast<int64>(microseconds); | 290 decoded_audio_duration_ = static_cast<int64>(microseconds); |
| 280 | 291 |
| 281 if (packet.pts == static_cast<int64>(AV_NOPTS_VALUE)) { | 292 if (packet.pts == static_cast<int64>(AV_NOPTS_VALUE)) { |
| 282 EXPECT_NE(decoded_audio_time_, static_cast<int64>(AV_NOPTS_VALUE)) | 293 EXPECT_NE(decoded_audio_time_, static_cast<int64>(AV_NOPTS_VALUE)) |
| 283 << "We never received an initial timestamped audio packet! " | 294 << "We never received an initial timestamped audio packet! " |
| 284 << "Looks like there's a seeking/parsing bug in FFmpeg."; | 295 << "Looks like there's a seeking/parsing bug in FFmpeg."; |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 static bool initialized = false; | 406 static bool initialized = false; |
| 396 if (initialized) { | 407 if (initialized) { |
| 397 return; | 408 return; |
| 398 } | 409 } |
| 399 | 410 |
| 400 FilePath path; | 411 FilePath path; |
| 401 PathService::Get(base::DIR_MODULE, &path); | 412 PathService::Get(base::DIR_MODULE, &path); |
| 402 EXPECT_TRUE(InitializeMediaLibrary(path)) | 413 EXPECT_TRUE(InitializeMediaLibrary(path)) |
| 403 << "Could not initialize media library."; | 414 << "Could not initialize media library."; |
| 404 | 415 |
| 405 avcodec_init(); | |
| 406 av_log_set_level(AV_LOG_FATAL); | 416 av_log_set_level(AV_LOG_FATAL); |
| 407 av_register_all(); | 417 av_register_all(); |
| 408 av_register_protocol2(&kFFmpegFileProtocol, sizeof(kFFmpegFileProtocol)); | 418 ffurl_register_protocol(&kFFmpegFileProtocol, sizeof(kFFmpegFileProtocol)); |
| 409 initialized = true; | 419 initialized = true; |
| 410 } | 420 } |
| 411 | 421 |
| 412 AVFormatContext* av_format_context_; | 422 AVFormatContext* av_format_context_; |
| 413 int audio_stream_index_; | 423 int audio_stream_index_; |
| 414 int video_stream_index_; | 424 int video_stream_index_; |
| 415 AVPacketQueue audio_packets_; | 425 AVPacketQueue audio_packets_; |
| 416 AVPacketQueue video_packets_; | 426 AVPacketQueue video_packets_; |
| 417 | 427 |
| 418 scoped_ptr_malloc<int16, media::ScopedPtrAVFree> audio_buffer_; | 428 scoped_ptr_malloc<int16, media::ScopedPtrAVFree> audio_buffer_; |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 SeekTo(0.4); | 656 SeekTo(0.4); |
| 647 ReadRemainingFile(); | 657 ReadRemainingFile(); |
| 648 EXPECT_TRUE(StepDecodeVideo()); | 658 EXPECT_TRUE(StepDecodeVideo()); |
| 649 VLOG(1) << decoded_video_time(); | 659 VLOG(1) << decoded_video_time(); |
| 650 | 660 |
| 651 CloseCodecs(); | 661 CloseCodecs(); |
| 652 CloseFile(); | 662 CloseFile(); |
| 653 } | 663 } |
| 654 | 664 |
| 655 } // namespace media | 665 } // namespace media |
| OLD | NEW |