summaryrefslogtreecommitdiffstats
path: root/media/mf/test/mft_h264_decoder_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'media/mf/test/mft_h264_decoder_unittest.cc')
-rw-r--r--media/mf/test/mft_h264_decoder_unittest.cc460
1 files changed, 0 insertions, 460 deletions
diff --git a/media/mf/test/mft_h264_decoder_unittest.cc b/media/mf/test/mft_h264_decoder_unittest.cc
deleted file mode 100644
index 11959f7..0000000
--- a/media/mf/test/mft_h264_decoder_unittest.cc
+++ /dev/null
@@ -1,460 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/file_path.h"
-#include "base/file_util.h"
-#include "base/message_loop.h"
-#include "base/path_service.h"
-#include "base/ref_counted.h"
-#include "base/scoped_ptr.h"
-#include "base/string_util.h"
-#include "base/time.h"
-#include "media/base/data_buffer.h"
-#include "media/base/video_frame.h"
-#include "media/mf/file_reader_util.h"
-#include "media/mf/mft_h264_decoder.h"
-#include "media/video/video_decode_engine.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::TimeDelta;
-
-namespace media {
-
-static const int kDecoderMaxWidth = 1920;
-static const int kDecoderMaxHeight = 1088;
-
-static HWND CreateDrawWindow(int width, int height) {
- static const wchar_t kClassName[] = L"Test";
- static const wchar_t kWindowTitle[] = L"MFT Unittest Draw Window";
- WNDCLASS window_class = {0};
- window_class.lpszClassName = kClassName;
- window_class.hInstance = NULL;
- window_class.hbrBackground = 0;
- window_class.lpfnWndProc = DefWindowProc;
- window_class.hCursor = 0;
-
- RegisterClass(&window_class);
-
- HWND window = CreateWindow(kClassName,
- kWindowTitle,
- (WS_OVERLAPPEDWINDOW | WS_VISIBLE) &
- ~(WS_MAXIMIZEBOX | WS_THICKFRAME),
- 100,
- 100,
- width,
- height,
- NULL,
- NULL,
- NULL,
- NULL);
- if (window == NULL) {
- LOG(ERROR) << "Failed to create window";
- return NULL;
- }
- return window;
-}
-
-class BaseMftReader : public base::RefCountedThreadSafe<BaseMftReader> {
- public:
- virtual ~BaseMftReader() {}
- virtual void ReadCallback(scoped_refptr<DataBuffer>* input) = 0;
-};
-
-class FakeMftReader : public BaseMftReader {
- public:
- FakeMftReader() : frames_remaining_(20) {}
- explicit FakeMftReader(int count) : frames_remaining_(count) {}
- virtual ~FakeMftReader() {}
-
- // Provides garbage input to the decoder.
- virtual void ReadCallback(scoped_refptr<DataBuffer>* input) {
- if (frames_remaining_ > 0) {
- int sz = 4096;
- uint8* buf = new uint8[sz];
- memset(buf, 42, sz);
- *input = new DataBuffer(buf, sz);
- (*input)->SetDuration(base::TimeDelta::FromMicroseconds(5000));
- (*input)->SetTimestamp(
- base::TimeDelta::FromMicroseconds(
- 50000000 - frames_remaining_ * 10000));
- --frames_remaining_;
- } else {
- // Emulate end of stream on the last "frame".
- *input = new DataBuffer(0);
- }
- }
- int frames_remaining() const { return frames_remaining_; }
-
- private:
- int frames_remaining_;
-};
-
-class FFmpegFileReaderWrapper : public BaseMftReader {
- public:
- FFmpegFileReaderWrapper() {}
- virtual ~FFmpegFileReaderWrapper() {}
- bool InitReader(const std::string& filename) {
- reader_.reset(new FFmpegFileReader(filename));
- if (!reader_.get() || !reader_->Initialize()) {
- reader_.reset();
- return false;
- }
- return true;
- }
- virtual void ReadCallback(scoped_refptr<DataBuffer>* input) {
- if (reader_.get()) {
- reader_->Read(input);
- }
- }
- bool GetWidth(int* width) {
- if (!reader_.get())
- return false;
- return reader_->GetWidth(width);
- }
- bool GetHeight(int* height) {
- if (!reader_.get())
- return false;
- return reader_->GetHeight(height);
- }
- scoped_ptr<FFmpegFileReader> reader_;
-};
-
-class MftH264DecoderTest : public testing::Test {
- public:
- MftH264DecoderTest() {}
- virtual ~MftH264DecoderTest() {}
-
- protected:
- virtual void SetUp() {}
- virtual void TearDown() {}
-};
-
-class SimpleMftH264DecoderHandler : public VideoDecodeEngine::EventHandler {
- public:
- SimpleMftH264DecoderHandler()
- : init_count_(0),
- uninit_count_(0),
- flush_count_(0),
- format_change_count_(0),
- empty_buffer_callback_count_(0),
- fill_buffer_callback_count_(0) {
- memset(&info_, 0, sizeof(info_));
- }
- virtual ~SimpleMftH264DecoderHandler() {}
- virtual void OnInitializeComplete(const VideoCodecInfo& info) {
- info_ = info;
- init_count_++;
- }
- virtual void OnUninitializeComplete() {
- uninit_count_++;
- }
- virtual void OnFlushComplete() {
- flush_count_++;
- }
- virtual void OnSeekComplete() {}
- virtual void OnError() {}
- virtual void OnFormatChange(VideoStreamInfo stream_info) {
- format_change_count_++;
- info_.stream_info = stream_info;
- }
- virtual void ProduceVideoSample(scoped_refptr<Buffer> buffer) {
- if (reader_.get() && decoder_) {
- empty_buffer_callback_count_++;
- scoped_refptr<DataBuffer> input;
- reader_->ReadCallback(&input);
- decoder_->ConsumeVideoSample(input);
- }
- }
- virtual void ConsumeVideoFrame(scoped_refptr<VideoFrame> frame) {
- fill_buffer_callback_count_++;
- current_frame_ = frame;
- }
- void SetReader(scoped_refptr<BaseMftReader> reader) {
- reader_ = reader;
- }
- void SetDecoder(MftH264Decoder* decoder) {
- decoder_ = decoder;
- }
-
- int init_count_;
- int uninit_count_;
- int flush_count_;
- int format_change_count_;
- int empty_buffer_callback_count_;
- int fill_buffer_callback_count_;
- VideoCodecInfo info_;
- scoped_refptr<BaseMftReader> reader_;
- MftH264Decoder* decoder_;
- scoped_refptr<VideoFrame> current_frame_;
-};
-
-// A simple test case for init/deinit of MF/COM libraries.
-TEST_F(MftH264DecoderTest, LibraryInit) {
- EXPECT_TRUE(MftH264Decoder::StartupComLibraries());
- MftH264Decoder::ShutdownComLibraries();
-}
-
-TEST_F(MftH264DecoderTest, DecoderUninitializedAtFirst) {
- scoped_ptr<MftH264Decoder> decoder(new MftH264Decoder(true, NULL));
- ASSERT_TRUE(decoder.get());
- EXPECT_EQ(MftH264Decoder::kUninitialized, decoder->state());
-}
-
-TEST_F(MftH264DecoderTest, DecoderInitMissingArgs) {
- VideoCodecConfig config;
- config.width = 800;
- config.height = 600;
- scoped_ptr<MftH264Decoder> decoder(new MftH264Decoder(false, NULL));
- ASSERT_TRUE(decoder.get());
- decoder->Initialize(NULL, NULL, NULL, config);
- EXPECT_EQ(MftH264Decoder::kUninitialized, decoder->state());
-}
-
-TEST_F(MftH264DecoderTest, DecoderInitNoDxva) {
- MessageLoop loop;
- SimpleMftH264DecoderHandler handler;
- VideoCodecConfig config;
- config.width = 800;
- config.height = 600;
- scoped_ptr<MftH264Decoder> decoder(new MftH264Decoder(false, NULL));
- ASSERT_TRUE(decoder.get());
- decoder->Initialize(&loop, &handler, NULL, config);
- EXPECT_EQ(1, handler.init_count_);
- EXPECT_EQ(MftH264Decoder::kNormal, decoder->state());
- decoder->Uninitialize();
-}
-
-TEST_F(MftH264DecoderTest, DecoderInitDxva) {
- MessageLoop loop;
- SimpleMftH264DecoderHandler handler;
- VideoCodecConfig config;
- config.width = 800;
- config.height = 600;
- HWND hwnd = CreateDrawWindow(config.width, config.height);
- ASSERT_TRUE(hwnd);
- scoped_ptr<MftH264Decoder> decoder(new MftH264Decoder(true, hwnd));
- ASSERT_TRUE(decoder.get());
- decoder->Initialize(&loop, &handler, NULL, config);
- EXPECT_EQ(1, handler.init_count_);
- EXPECT_EQ(MftH264Decoder::kNormal, decoder->state());
- decoder->Uninitialize();
- DestroyWindow(hwnd);
-}
-
-TEST_F(MftH264DecoderTest, DecoderUninit) {
- MessageLoop loop;
- SimpleMftH264DecoderHandler handler;
- VideoCodecConfig config;
- config.width = 800;
- config.height = 600;
- scoped_ptr<MftH264Decoder> decoder(new MftH264Decoder(false, NULL));
- ASSERT_TRUE(decoder.get());
- decoder->Initialize(&loop, &handler, NULL, config);
- EXPECT_EQ(MftH264Decoder::kNormal, decoder->state());
- decoder->Uninitialize();
- EXPECT_EQ(1, handler.uninit_count_);
- EXPECT_EQ(MftH264Decoder::kUninitialized, decoder->state());
-}
-
-TEST_F(MftH264DecoderTest, UninitBeforeInit) {
- MessageLoop loop;
- SimpleMftH264DecoderHandler handler;
- VideoCodecConfig config;
- config.width = 800;
- config.height = 600;
- scoped_ptr<MftH264Decoder> decoder(new MftH264Decoder(false, NULL));
- ASSERT_TRUE(decoder.get());
- decoder->Uninitialize();
- EXPECT_EQ(0, handler.uninit_count_);
-}
-
-TEST_F(MftH264DecoderTest, InitWithNegativeDimensions) {
- MessageLoop loop;
- SimpleMftH264DecoderHandler handler;
- VideoCodecConfig config;
- config.width = -123;
- config.height = -456;
- scoped_ptr<MftH264Decoder> decoder(new MftH264Decoder(false, NULL));
- ASSERT_TRUE(decoder.get());
- decoder->Initialize(&loop, &handler, NULL, config);
- EXPECT_EQ(MftH264Decoder::kNormal, decoder->state());
- EXPECT_EQ(kDecoderMaxWidth, handler.info_.stream_info.surface_width);
- EXPECT_EQ(kDecoderMaxHeight, handler.info_.stream_info.surface_height);
- decoder->Uninitialize();
-}
-
-TEST_F(MftH264DecoderTest, InitWithTooHighDimensions) {
- MessageLoop loop;
- SimpleMftH264DecoderHandler handler;
- VideoCodecConfig config;
- config.width = kDecoderMaxWidth + 1;
- config.height = kDecoderMaxHeight + 1;
- scoped_ptr<MftH264Decoder> decoder(new MftH264Decoder(false, NULL));
- ASSERT_TRUE(decoder.get());
- decoder->Initialize(&loop, &handler, NULL, config);
- EXPECT_EQ(MftH264Decoder::kNormal, decoder->state());
- EXPECT_EQ(kDecoderMaxWidth, handler.info_.stream_info.surface_width);
- EXPECT_EQ(kDecoderMaxHeight, handler.info_.stream_info.surface_height);
- decoder->Uninitialize();
-}
-
-TEST_F(MftH264DecoderTest, DrainOnEmptyBuffer) {
- MessageLoop loop;
- SimpleMftH264DecoderHandler handler;
- VideoCodecConfig config;
- config.width = 1024;
- config.height = 768;
- scoped_ptr<MftH264Decoder> decoder(new MftH264Decoder(false, NULL));
- ASSERT_TRUE(decoder.get());
- decoder->Initialize(&loop, &handler, NULL, config);
- EXPECT_EQ(MftH264Decoder::kNormal, decoder->state());
- scoped_refptr<Buffer> buffer(new DataBuffer(0));
-
- // Decoder should switch to drain mode because of this NULL buffer, and then
- // switch to kStopped when it says it needs more input during drain mode.
- decoder->ConsumeVideoSample(buffer);
- EXPECT_EQ(MftH264Decoder::kStopped, decoder->state());
-
- // Should have called back with one empty frame.
- EXPECT_EQ(1, handler.fill_buffer_callback_count_);
- ASSERT_TRUE(handler.current_frame_.get());
- EXPECT_EQ(VideoFrame::EMPTY, handler.current_frame_->format());
- decoder->Uninitialize();
-}
-
-TEST_F(MftH264DecoderTest, NoOutputOnGarbageInput) {
- // 100 samples of garbage.
- const int kNumFrames = 100;
- scoped_refptr<FakeMftReader> reader(new FakeMftReader(kNumFrames));
- ASSERT_TRUE(reader.get());
-
- MessageLoop loop;
- SimpleMftH264DecoderHandler handler;
- VideoCodecConfig config;
- config.width = 1024;
- config.height = 768;
- scoped_ptr<MftH264Decoder> decoder(new MftH264Decoder(false, NULL));
- ASSERT_TRUE(decoder.get());
- decoder->Initialize(&loop, &handler, NULL, config);
- EXPECT_EQ(MftH264Decoder::kNormal, decoder->state());
- handler.SetReader(reader);
- handler.SetDecoder(decoder.get());
- while (MftH264Decoder::kStopped != decoder->state()) {
- scoped_refptr<VideoFrame> frame;
- decoder->ProduceVideoFrame(frame);
- }
-
- // Output callback should only be invoked once - the empty frame to indicate
- // end of stream.
- EXPECT_EQ(1, handler.fill_buffer_callback_count_);
- ASSERT_TRUE(handler.current_frame_.get());
- EXPECT_EQ(VideoFrame::EMPTY, handler.current_frame_->format());
-
- // One extra count because of the end of stream NULL sample.
- EXPECT_EQ(kNumFrames, handler.empty_buffer_callback_count_ - 1);
- decoder->Uninitialize();
-}
-
-TEST_F(MftH264DecoderTest, FlushAtStart) {
- MessageLoop loop;
- SimpleMftH264DecoderHandler handler;
- VideoCodecConfig config;
- config.width = 1024;
- config.height = 768;
- scoped_ptr<MftH264Decoder> decoder(new MftH264Decoder(false, NULL));
- ASSERT_TRUE(decoder.get());
- decoder->Initialize(&loop, &handler, NULL, config);
- EXPECT_EQ(MftH264Decoder::kNormal, decoder->state());
- decoder->Flush();
-
- // Flush should succeed even if input/output are empty.
- EXPECT_EQ(1, handler.flush_count_);
- decoder->Uninitialize();
-}
-
-TEST_F(MftH264DecoderTest, NoFlushAtStopped) {
- scoped_refptr<BaseMftReader> reader(new FakeMftReader());
- ASSERT_TRUE(reader.get());
-
- MessageLoop loop;
- SimpleMftH264DecoderHandler handler;
- VideoCodecConfig config;
- config.width = 1024;
- config.height = 768;
- scoped_ptr<MftH264Decoder> decoder(new MftH264Decoder(false, NULL));
- ASSERT_TRUE(decoder.get());
- decoder->Initialize(&loop, &handler, NULL, config);
- EXPECT_EQ(MftH264Decoder::kNormal, decoder->state());
- handler.SetReader(reader);
- handler.SetDecoder(decoder.get());
- while (MftH264Decoder::kStopped != decoder->state()) {
- scoped_refptr<VideoFrame> frame;
- decoder->ProduceVideoFrame(frame);
- }
- EXPECT_EQ(0, handler.flush_count_);
- int old_flush_count = handler.flush_count_;
- decoder->Flush();
- EXPECT_EQ(old_flush_count, handler.flush_count_);
- decoder->Uninitialize();
-}
-
-FilePath GetVideoFilePath(const std::string& file_name) {
- FilePath path;
- PathService::Get(base::DIR_SOURCE_ROOT, &path);
- path = path.AppendASCII("media")
- .AppendASCII("test")
- .AppendASCII("data")
- .AppendASCII(file_name.c_str());
- return path;
-}
-
-void DecodeValidVideo(const std::string& filename, int num_frames, bool dxva) {
- scoped_refptr<FFmpegFileReaderWrapper> reader(new FFmpegFileReaderWrapper());
- ASSERT_TRUE(reader.get());
- FilePath path = GetVideoFilePath(filename);
- ASSERT_TRUE(file_util::PathExists(path));
- ASSERT_TRUE(reader->InitReader(WideToASCII(path.value())));
- int actual_width;
- int actual_height;
- ASSERT_TRUE(reader->GetWidth(&actual_width));
- ASSERT_TRUE(reader->GetHeight(&actual_height));
-
- MessageLoop loop;
- SimpleMftH264DecoderHandler handler;
- VideoCodecConfig config;
- config.width = 1;
- config.height = 1;
- HWND hwnd = CreateDrawWindow(config.width, config.height);
- ASSERT_TRUE(hwnd);
- scoped_ptr<MftH264Decoder> decoder(new MftH264Decoder(dxva, hwnd));
- ASSERT_TRUE(decoder.get());
- decoder->Initialize(&loop, &handler, NULL, config);
- EXPECT_EQ(MftH264Decoder::kNormal, decoder->state());
- handler.SetReader(reader);
- handler.SetDecoder(decoder.get());
- while (MftH264Decoder::kStopped != decoder->state()) {
- scoped_refptr<VideoFrame> frame;
- decoder->ProduceVideoFrame(frame);
- }
-
- // We expect a format change when decoder receives enough data to determine
- // the actual frame width/height.
- EXPECT_GT(handler.format_change_count_, 0);
- EXPECT_EQ(actual_width, handler.info_.stream_info.surface_width);
- EXPECT_EQ(actual_height, handler.info_.stream_info.surface_height);
- EXPECT_GE(handler.empty_buffer_callback_count_, num_frames);
- EXPECT_EQ(num_frames, handler.fill_buffer_callback_count_ - 1);
- decoder->Uninitialize();
- DestroyWindow(hwnd);
-}
-
-TEST_F(MftH264DecoderTest, DecodeValidVideoDxva) {
- DecodeValidVideo("bear.1280x720.mp4", 82, true);
-}
-
-TEST_F(MftH264DecoderTest, DecodeValidVideoNoDxva) {
- DecodeValidVideo("bear.1280x720.mp4", 82, false);
-}
-
-} // namespace media