summaryrefslogtreecommitdiffstats
path: root/media/mf
diff options
context:
space:
mode:
Diffstat (limited to 'media/mf')
-rw-r--r--media/mf/README.chromium23
-rw-r--r--media/mf/file_reader_util.cc211
-rw-r--r--media/mf/file_reader_util.h70
-rw-r--r--media/mf/mft_h264_decoder.cc706
-rw-r--r--media/mf/mft_h264_decoder.h97
-rw-r--r--media/mf/mft_h264_decoder_example.cc421
-rw-r--r--media/mf/test/mft_h264_decoder_unittest.cc460
-rw-r--r--media/mf/test/run_all_unittests.cc26
8 files changed, 0 insertions, 2014 deletions
diff --git a/media/mf/README.chromium b/media/mf/README.chromium
deleted file mode 100644
index 73f1deb..0000000
--- a/media/mf/README.chromium
+++ /dev/null
@@ -1,23 +0,0 @@
-This tool demonstrates the use of the Media Foundation H.264 decoder as a
-standalone Media Foundation Transform (MFT). The H.264 decoder takes sample
-objects (IMFSample) containing Annex B streams as input, and outputs decoded
-YV12/NV12 video frames as output, contained in a buffer object (if DXVA is not
-enabled) or a Direct3D surface (if DXVA is enabled.)
-
-This tool uses ffmpeg's parser and bitstream converter to read a file
-containing H.264 video and outputs packets containing Annex B streams which are
-then fed into the H.264 decoder. This tool also demonstrates the use of the
-H.264 decoder using callbacks.
-
-Requirements: Windows 7
-
-Note1: On some video files, there is a mysterious 1-off decoded frame count
-when DXVA is enabled.
-
-Note2: This tool requires the ffmpeg library to have the H.264 codec and Annex
-B bitstream filter. You might need build your own, or grab one from
-http://ffmpeg.arrozcru.org/autobuilds/
-
-Note3: A single H264Mft instance is only for 1 H.264 video stream only.
-Inputting streams consisting of more than 1 video to a single instance
-may result in undefined behavior.
diff --git a/media/mf/file_reader_util.cc b/media/mf/file_reader_util.cc
deleted file mode 100644
index d18afe6..0000000
--- a/media/mf/file_reader_util.cc
+++ /dev/null
@@ -1,211 +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.
-//
-// Borrowed from media/tools/omx_test/file_reader_util.cc.
-// Added some functionalities related to timestamps on packets.
-
-#include "media/mf/file_reader_util.h"
-
-#include <cstring>
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "media/base/data_buffer.h"
-#include "media/ffmpeg/ffmpeg_common.h"
-#include "media/filters/bitstream_converter.h"
-
-namespace media {
-
-//////////////////////////////////////////////////////////////////////////////
-// FFmpegFileReader
-FFmpegFileReader::FFmpegFileReader(const std::string& filename)
- : filename_(filename),
- format_context_(NULL),
- codec_context_(NULL),
- target_stream_(-1),
- converter_(NULL),
- last_timestamp_(0) {
-}
-
-FFmpegFileReader::~FFmpegFileReader() {
- if (format_context_)
- av_close_input_file(format_context_);
-}
-
-bool FFmpegFileReader::Initialize() {
- int result = av_open_input_file(&format_context_, filename_.c_str(),
- NULL, 0, NULL);
- if (result < 0) {
- switch (result) {
- case AVERROR_NOFMT:
- LOG(ERROR) << "Error: File format not supported "
- << filename_;
- break;
- default:
- LOG(ERROR) << "Error: Could not open input for "
- << filename_ << ": " << result;
- break;
- }
- return false;
- }
- if (av_find_stream_info(format_context_) < 0) {
- LOG(ERROR) << "can't use FFmpeg to parse stream info";
- return false;
- }
-
- for (size_t i = 0; i < format_context_->nb_streams; ++i) {
- codec_context_ = format_context_->streams[i]->codec;
-
- // Find the video stream.
- if (codec_context_->codec_type == CODEC_TYPE_VIDEO) {
- target_stream_ = i;
- break;
- }
- }
- if (target_stream_ == -1) {
- LOG(ERROR) << "no video in the stream";
- return false;
- }
-
- // Initialize the bitstream filter if needed.
- // TODO(hclam): find a better way to identify mp4 container.
- if (codec_context_->codec_id == CODEC_ID_H264) {
- converter_.reset(new media::FFmpegBitstreamConverter(
- "h264_mp4toannexb", codec_context_));
- } else if (codec_context_->codec_id == CODEC_ID_MPEG4) {
- converter_.reset(new media::FFmpegBitstreamConverter(
- "mpeg4video_es", codec_context_));
- } else if (codec_context_->codec_id == CODEC_ID_WMV3) {
- converter_.reset(new media::FFmpegBitstreamConverter(
- "vc1_asftorcv", codec_context_));
- } else if (codec_context_->codec_id == CODEC_ID_VC1) {
- converter_.reset(new media::FFmpegBitstreamConverter(
- "vc1_asftoannexg", codec_context_));
- }
- if (converter_.get() && !converter_->Initialize()) {
- converter_.reset();
- LOG(ERROR) << "failed to initialize h264_mp4toannexb filter";
- return false;
- }
- return true;
-}
-
-void FFmpegFileReader::Read(scoped_refptr<DataBuffer>* output) {
- if (!format_context_ || !codec_context_ || target_stream_ == -1) {
- *output = new DataBuffer(0);
- return;
- }
- AVPacket packet;
- bool found = false;
- while (!found) {
- int result = av_read_frame(format_context_, &packet);
- if (result < 0) {
- *output = new DataBuffer(0);
- return;
- }
- if (packet.stream_index == target_stream_) {
- if (converter_.get() && !converter_->ConvertPacket(&packet)) {
- LOG(ERROR) << "failed to convert AVPacket";
- }
- last_timestamp_ = std::max(last_timestamp_, packet.pts);
- CopyPacketToBuffer(&packet, output);
- found = true;
- }
- av_free_packet(&packet);
- }
-}
-
-bool FFmpegFileReader::SeekForward(int64 seek_amount_us) {
- if (!format_context_ || !codec_context_ || target_stream_ == -1) {
- return false;
- }
- int64 new_us = TimeBaseToMicroseconds(last_timestamp_) + seek_amount_us;
- int64 new_timestamp = MicrosecondsToTimeBase(new_us);
- last_timestamp_ = new_timestamp;
- return av_seek_frame(format_context_, target_stream_, new_timestamp, 0) >= 0;
-}
-
-bool FFmpegFileReader::GetFrameRate(int* num, int* denom) const {
- if (!codec_context_)
- return false;
- *denom = codec_context_->time_base.num;
- *num = codec_context_->time_base.den;
- if (*denom == 0) {
- *num = 0;
- return false;
- }
- return true;
-}
-
-bool FFmpegFileReader::GetWidth(int* width) const {
- if (!codec_context_)
- return false;
- *width = codec_context_->width;
- return true;
-}
-
-bool FFmpegFileReader::GetHeight(int* height) const {
- if (!codec_context_)
- return false;
- *height = codec_context_->height;
- return true;
-}
-
-bool FFmpegFileReader::GetAspectRatio(int* num, int* denom) const {
- if (!codec_context_)
- return false;
- AVRational aspect_ratio = codec_context_->sample_aspect_ratio;
- if (aspect_ratio.num == 0 || aspect_ratio.den == 0)
- return false;
- *num = aspect_ratio.num;
- *denom = aspect_ratio.den;
- return true;
-}
-
-int64 FFmpegFileReader::TimeBaseToMicroseconds(
- int64 time_base_unit) const {
- // FFmpeg units after time base conversion seems to be actually given in
- // milliseconds (instead of seconds...) so we need to multiply it by a factor
- // of 1,000.
- // Note we need to double this because the frame rate is doubled in
- // ffmpeg.
- CHECK(codec_context_) << "Codec context needs to be initialized";
- return time_base_unit * 2000 * codec_context_->time_base.num /
- codec_context_->time_base.den;
-}
-
-int64 FFmpegFileReader::MicrosecondsToTimeBase(
- int64 time_base_unit) const {
- CHECK(codec_context_) << "Codec context needs to be initialized";
- return time_base_unit * codec_context_->time_base.den / 2000 /
- codec_context_->time_base.num;
-}
-
-void FFmpegFileReader::CopyPacketToBuffer(AVPacket* packet,
- scoped_refptr<DataBuffer>* output) {
- uint8* buffer = new uint8[packet->size];
- if (buffer == NULL) {
- LOG(ERROR) << "Failed to allocate buffer for annex b stream";
- *output = NULL;
- return;
- }
- memcpy(buffer, packet->data, packet->size);
- *output = new DataBuffer(buffer, packet->size);
- if (packet->pts != AV_NOPTS_VALUE) {
- (*output)->SetTimestamp(
- base::TimeDelta::FromMicroseconds(
- TimeBaseToMicroseconds(packet->pts)));
- } else {
- (*output)->SetTimestamp(StreamSample::kInvalidTimestamp);
- }
- if (packet->duration == 0) {
- LOG(WARNING) << "Packet duration not known";
- }
- (*output)->SetDuration(
- base::TimeDelta::FromMicroseconds(
- TimeBaseToMicroseconds(packet->duration)));
-}
-
-} // namespace media
diff --git a/media/mf/file_reader_util.h b/media/mf/file_reader_util.h
deleted file mode 100644
index a5fa9ec..0000000
--- a/media/mf/file_reader_util.h
+++ /dev/null
@@ -1,70 +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.
-//
-// Borrowed from media/tools/omx_test/file_reader_util.h.
-// Added some functionalities related to timestamps on packets and Media
-// Foundation.
-
-#ifndef MEDIA_MF_FILE_READER_UTIL_H_
-#define MEDIA_MF_FILE_READER_UTIL_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/ref_counted.h"
-#include "base/scoped_ptr.h"
-
-struct AVCodecContext;
-struct AVFormatContext;
-struct AVPacket;
-
-namespace media {
-
-class BitstreamConverter;
-class DataBuffer;
-
-// A class to help reading and parsing input file for use in omx_test.
-class FileReader {
- public:
- virtual ~FileReader() {}
-
- // Initialize FileReader object, returns true if successful.
- virtual bool Initialize() = 0;
-
- // Read the file into |output|, and output the number of bytes read to
- // |size|.
- virtual void Read(scoped_refptr<DataBuffer>* output) = 0;
-};
-
-class FFmpegFileReader : public FileReader {
- public:
- explicit FFmpegFileReader(const std::string& filename);
- virtual ~FFmpegFileReader();
- virtual bool Initialize();
- virtual void Read(scoped_refptr<DataBuffer>* output);
- virtual bool SeekForward(int64 seek_amount_us);
-
- bool GetFrameRate(int* num, int* denom) const;
- bool GetWidth(int* width) const;
- bool GetHeight(int* height) const;
- bool GetAspectRatio(int* num, int* denom) const;
- int64 TimeBaseToMicroseconds(int64 time_base_unit) const;
- int64 MicrosecondsToTimeBase(int64 time_base_unit) const;
-
- private:
- void CopyPacketToBuffer(AVPacket* packet, scoped_refptr<DataBuffer>* output);
-
- std::string filename_;
- AVFormatContext* format_context_;
- AVCodecContext* codec_context_;
- int target_stream_;
- scoped_ptr<BitstreamConverter> converter_;
- int64 last_timestamp_;
-
- DISALLOW_COPY_AND_ASSIGN(FFmpegFileReader);
-};
-
-} // namespace media
-
-#endif // MEDIA_MF_FILE_READER_UTIL_H_
diff --git a/media/mf/mft_h264_decoder.cc b/media/mf/mft_h264_decoder.cc
deleted file mode 100644
index 2c1970d..0000000
--- a/media/mf/mft_h264_decoder.cc
+++ /dev/null
@@ -1,706 +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 "media/mf/mft_h264_decoder.h"
-
-#include <d3d9.h>
-#include <dxva2api.h>
-#include <initguid.h>
-#include <mfapi.h>
-// Placed after mfapi.h to avoid linking strmiids.lib for MR_BUFFER_SERVICE.
-#include <evr.h>
-#include <mferror.h>
-#include <wmcodecdsp.h>
-
-#include "base/time.h"
-#include "base/message_loop.h"
-
-#pragma comment(lib, "dxva2.lib")
-#pragma comment(lib, "d3d9.lib")
-#pragma comment(lib, "mf.lib")
-#pragma comment(lib, "mfplat.lib")
-
-using base::TimeDelta;
-
-namespace {
-
-// Creates an empty Media Foundation sample with no buffers.
-static IMFSample* CreateEmptySample() {
- HRESULT hr;
- ScopedComPtr<IMFSample> sample;
- hr = MFCreateSample(sample.Receive());
- if (FAILED(hr)) {
- LOG(ERROR) << "Unable to create an empty sample";
- return NULL;
- }
- return sample.Detach();
-}
-
-// Creates a Media Foundation sample with one buffer of length |buffer_length|
-// on a |align|-byte boundary. Alignment must be a perfect power of 2 or 0.
-// If |align| is 0, then no alignment is specified.
-static IMFSample* CreateEmptySampleWithBuffer(int buffer_length, int align) {
- CHECK_GT(buffer_length, 0);
- ScopedComPtr<IMFSample> sample;
- sample.Attach(CreateEmptySample());
- if (!sample.get())
- return NULL;
- ScopedComPtr<IMFMediaBuffer> buffer;
- HRESULT hr;
- if (align == 0) {
- // Note that MFCreateMemoryBuffer is same as MFCreateAlignedMemoryBuffer
- // with the align argument being 0.
- hr = MFCreateMemoryBuffer(buffer_length, buffer.Receive());
- } else {
- hr = MFCreateAlignedMemoryBuffer(buffer_length,
- align - 1,
- buffer.Receive());
- }
- if (FAILED(hr)) {
- LOG(ERROR) << "Unable to create an empty buffer";
- return NULL;
- }
- hr = sample->AddBuffer(buffer.get());
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to add empty buffer to sample";
- return NULL;
- }
- return sample.Detach();
-}
-
-// Creates a Media Foundation sample with one buffer containing a copy of the
-// given Annex B stream data.
-// If duration and sample time are not known, provide 0.
-// |min_size| specifies the minimum size of the buffer (might be required by
-// the decoder for input). The times here should be given in 100ns units.
-// |alignment| specifies the buffer in the sample to be aligned. If no
-// alignment is required, provide 0 or 1.
-static IMFSample* CreateInputSample(const uint8* stream, int size,
- int64 timestamp, int64 duration,
- int min_size, int alignment) {
- CHECK(stream);
- CHECK_GT(size, 0);
- ScopedComPtr<IMFSample> sample;
- sample.Attach(CreateEmptySampleWithBuffer(std::max(min_size, size),
- alignment));
- if (!sample.get()) {
- LOG(ERROR) << "Failed to create empty buffer for input";
- return NULL;
- }
- HRESULT hr;
- if (duration > 0) {
- hr = sample->SetSampleDuration(duration);
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to set sample duration";
- return NULL;
- }
- }
- if (timestamp > 0) {
- hr = sample->SetSampleTime(timestamp);
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to set sample time";
- return NULL;
- }
- }
- ScopedComPtr<IMFMediaBuffer> buffer;
- hr = sample->GetBufferByIndex(0, buffer.Receive());
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to get buffer in sample";
- return NULL;
- }
- DWORD max_length, current_length;
- uint8* destination;
- hr = buffer->Lock(&destination, &max_length, &current_length);
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to lock buffer";
- return NULL;
- }
- CHECK_EQ(current_length, 0u);
- CHECK_GE(static_cast<int>(max_length), size);
- memcpy(destination, stream, size);
- CHECK(SUCCEEDED(buffer->Unlock()));
- hr = buffer->SetCurrentLength(size);
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to set current length to " << size;
- return NULL;
- }
- LOG(INFO) << __FUNCTION__ << " wrote " << size << " bytes into input sample";
- return sample.Detach();
-}
-
-const GUID ConvertVideoFrameFormatToGuid(media::VideoFrame::Format format) {
- switch (format) {
- case media::VideoFrame::NV12:
- return MFVideoFormat_NV12;
- case media::VideoFrame::YV12:
- return MFVideoFormat_YV12;
- default:
- NOTREACHED() << "Unsupported VideoFrame format";
- return GUID_NULL;
- }
- NOTREACHED();
- return GUID_NULL;
-}
-
-} // namespace
-
-namespace media {
-
-// public methods
-
-MftH264Decoder::MftH264Decoder(bool use_dxva, HWND draw_window)
- : use_dxva_(use_dxva),
- d3d9_(NULL),
- device_(NULL),
- device_manager_(NULL),
- draw_window_(draw_window),
- decoder_(NULL),
- input_stream_info_(),
- output_stream_info_(),
- state_(kUninitialized),
- event_handler_(NULL) {
- memset(&config_, 0, sizeof(config_));
- memset(&info_, 0, sizeof(info_));
-}
-
-MftH264Decoder::~MftH264Decoder() {
-}
-
-void MftH264Decoder::Initialize(
- MessageLoop* message_loop,
- VideoDecodeEngine::EventHandler* event_handler,
- VideoDecodeContext* context,
- const VideoCodecConfig& config) {
- LOG(INFO) << "MftH264Decoder::Initialize";
- if (state_ != kUninitialized) {
- LOG(ERROR) << "Initialize: invalid state";
- return;
- }
- if (!message_loop || !event_handler) {
- LOG(ERROR) << "MftH264Decoder::Initialize: parameters cannot be NULL";
- return;
- }
-
- config_ = config;
- event_handler_ = event_handler;
-
- info_.provides_buffers = true;
-
- // TODO(jiesun): Actually it is more likely an NV12 D3DSuface9.
- // Until we had hardware composition working.
- if (use_dxva_) {
- info_.stream_info.surface_format = VideoFrame::NV12;
- info_.stream_info.surface_type = VideoFrame::TYPE_GL_TEXTURE;
- } else {
- info_.stream_info.surface_format = VideoFrame::YV12;
- info_.stream_info.surface_type = VideoFrame::TYPE_SYSTEM_MEMORY;
- }
-
- // codec_info.stream_info_.surface_width_/height_ are initialized
- // in InitInternal().
- info_.success = InitInternal();
- if (info_.success) {
- state_ = kNormal;
- event_handler_->OnInitializeComplete(info_);
- } else {
- LOG(ERROR) << "MftH264Decoder::Initialize failed";
- }
-}
-
-void MftH264Decoder::Uninitialize() {
- LOG(INFO) << "MftH264Decoder::Uninitialize";
- if (state_ == kUninitialized) {
- LOG(ERROR) << "Uninitialize: invalid state";
- return;
- }
-
- // TODO(imcheng):
- // Cannot shutdown COM libraries here because the COM objects still needs
- // to be Release()'ed. We can explicitly release them here, or move the
- // uninitialize to GpuVideoService...
- decoder_.Release();
- device_manager_.Release();
- device_.Release();
- d3d9_.Release();
- ShutdownComLibraries();
- state_ = kUninitialized;
- event_handler_->OnUninitializeComplete();
-}
-
-void MftH264Decoder::Flush() {
- LOG(INFO) << "MftH264Decoder::Flush";
- if (state_ != kNormal) {
- LOG(ERROR) << "Flush: invalid state";
- return;
- }
- state_ = kFlushing;
- if (!SendMFTMessage(MFT_MESSAGE_COMMAND_FLUSH)) {
- LOG(WARNING) << "MftH264Decoder::Flush failed to send message";
- }
- state_ = kNormal;
- event_handler_->OnFlushComplete();
-}
-
-void MftH264Decoder::Seek() {
- if (state_ != kNormal) {
- LOG(ERROR) << "Seek: invalid state";
- return;
- }
- LOG(INFO) << "MftH264Decoder::Seek";
- // Seek not implemented.
- event_handler_->OnSeekComplete();
-}
-
-void MftH264Decoder::ConsumeVideoSample(scoped_refptr<Buffer> buffer) {
- LOG(INFO) << "MftH264Decoder::ConsumeVideoSample";
- if (state_ == kUninitialized) {
- LOG(ERROR) << "ConsumeVideoSample: invalid state";
- }
- ScopedComPtr<IMFSample> sample;
- if (!buffer->IsEndOfStream()) {
- sample.Attach(
- CreateInputSample(buffer->GetData(),
- buffer->GetDataSize(),
- buffer->GetTimestamp().InMicroseconds() * 10,
- buffer->GetDuration().InMicroseconds() * 10,
- input_stream_info_.cbSize,
- input_stream_info_.cbAlignment));
- if (!sample.get()) {
- LOG(ERROR) << "Failed to create an input sample";
- } else {
- if (FAILED(decoder_->ProcessInput(0, sample.get(), 0))) {
- event_handler_->OnError();
- }
- }
- } else {
- if (state_ != MftH264Decoder::kEosDrain) {
- // End of stream, send drain messages.
- if (!SendMFTMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM) ||
- !SendMFTMessage(MFT_MESSAGE_COMMAND_DRAIN)) {
- LOG(ERROR) << "Failed to send EOS / drain messages to MFT";
- event_handler_->OnError();
- } else {
- state_ = MftH264Decoder::kEosDrain;
- }
- }
- }
- DoDecode();
-}
-
-void MftH264Decoder::ProduceVideoFrame(scoped_refptr<VideoFrame> frame) {
- LOG(INFO) << "MftH264Decoder::ProduceVideoFrame";
- if (state_ == kUninitialized) {
- LOG(ERROR) << "ProduceVideoFrame: invalid state";
- return;
- }
- scoped_refptr<Buffer> buffer;
- event_handler_->ProduceVideoSample(buffer);
-}
-
-// private methods
-
-// static
-bool MftH264Decoder::StartupComLibraries() {
- HRESULT hr;
- hr = CoInitializeEx(NULL,
- COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
- if (FAILED(hr)) {
- LOG(ERROR) << "CoInit fail";
- return false;
- }
-
- hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
- if (FAILED(hr)) {
- LOG(ERROR) << "MFStartup fail";
- CoUninitialize();
- return false;
- }
- return true;
-}
-
-// static
-void MftH264Decoder::ShutdownComLibraries() {
- HRESULT hr;
- hr = MFShutdown();
- if (FAILED(hr)) {
- LOG(WARNING) << "Warning: MF failed to shutdown";
- }
- CoUninitialize();
-}
-
-bool MftH264Decoder::CreateD3DDevManager() {
- CHECK(draw_window_);
- d3d9_.Attach(Direct3DCreate9(D3D_SDK_VERSION));
- if (d3d9_.get() == NULL) {
- LOG(ERROR) << "Failed to create D3D9";
- return false;
- }
-
- D3DPRESENT_PARAMETERS present_params = {0};
- present_params.BackBufferWidth = 0;
- present_params.BackBufferHeight = 0;
- present_params.BackBufferFormat = D3DFMT_UNKNOWN;
- present_params.BackBufferCount = 1;
- present_params.SwapEffect = D3DSWAPEFFECT_DISCARD;
- present_params.hDeviceWindow = draw_window_;
- present_params.Windowed = TRUE;
- present_params.Flags = D3DPRESENTFLAG_VIDEO;
- present_params.FullScreen_RefreshRateInHz = 0;
- present_params.PresentationInterval = 0;
-
- // D3DCREATE_HARDWARE_VERTEXPROCESSING specifies hardware vertex processing.
- // (Is it even needed for just video decoding?)
- HRESULT hr = d3d9_->CreateDevice(D3DADAPTER_DEFAULT,
- D3DDEVTYPE_HAL,
- draw_window_,
- (D3DCREATE_HARDWARE_VERTEXPROCESSING |
- D3DCREATE_MULTITHREADED),
- &present_params,
- device_.Receive());
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to create D3D Device";
- return false;
- }
-
- UINT dev_manager_reset_token = 0;
- hr = DXVA2CreateDirect3DDeviceManager9(&dev_manager_reset_token,
- device_manager_.Receive());
- if (FAILED(hr)) {
- LOG(ERROR) << "Couldn't create D3D Device manager";
- return false;
- }
-
- hr = device_manager_->ResetDevice(device_.get(),
- dev_manager_reset_token);
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to set device to device manager";
- return false;
- }
- return true;
-}
-
-bool MftH264Decoder::InitInternal() {
- if (!StartupComLibraries())
- return false;
- if (use_dxva_ && !CreateD3DDevManager())
- return false;
- if (!InitDecoder())
- return false;
- if (!GetStreamsInfoAndBufferReqs())
- return false;
- return SendMFTMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING);
-}
-
-bool MftH264Decoder::InitDecoder() {
- // TODO(jiesun): use MFEnum to get decoder CLSID.
- HRESULT hr = CoCreateInstance(__uuidof(CMSH264DecoderMFT),
- NULL,
- CLSCTX_INPROC_SERVER,
- __uuidof(IMFTransform),
- reinterpret_cast<void**>(decoder_.Receive()));
- if (FAILED(hr) || !decoder_.get()) {
- LOG(ERROR) << "CoCreateInstance failed " << std::hex << std::showbase << hr;
- return false;
- }
-
- if (!CheckDecoderDxvaSupport())
- return false;
-
- if (use_dxva_) {
- hr = decoder_->ProcessMessage(
- MFT_MESSAGE_SET_D3D_MANAGER,
- reinterpret_cast<ULONG_PTR>(device_manager_.get()));
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to set D3D9 device to decoder " << std::hex << hr;
- return false;
- }
- }
-
- return SetDecoderMediaTypes();
-}
-
-bool MftH264Decoder::CheckDecoderDxvaSupport() {
- ScopedComPtr<IMFAttributes> attributes;
- HRESULT hr = decoder_->GetAttributes(attributes.Receive());
- if (FAILED(hr)) {
- LOG(ERROR) << "Unlock: Failed to get attributes, hr = "
- << std::hex << std::showbase << hr;
- return false;
- }
-
- UINT32 dxva;
- hr = attributes->GetUINT32(MF_SA_D3D_AWARE, &dxva);
- if (FAILED(hr) || !dxva) {
- LOG(ERROR) << "Failed to get DXVA attr or decoder is not DXVA-aware, hr = "
- << std::hex << std::showbase << hr
- << " this might not be the right decoder.";
- return false;
- }
- return true;
-}
-
-bool MftH264Decoder::SetDecoderMediaTypes() {
- if (!SetDecoderInputMediaType())
- return false;
- return SetDecoderOutputMediaType(ConvertVideoFrameFormatToGuid(
- info_.stream_info.surface_format));
-}
-
-bool MftH264Decoder::SetDecoderInputMediaType() {
- ScopedComPtr<IMFMediaType> media_type;
- HRESULT hr = MFCreateMediaType(media_type.Receive());
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to create empty media type object";
- return false;
- }
-
- hr = media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
- if (FAILED(hr)) {
- LOG(ERROR) << "SetGUID for major type failed";
- return false;
- }
-
- hr = media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264);
- if (FAILED(hr)) {
- LOG(ERROR) << "SetGUID for subtype failed";
- return false;
- }
-
- hr = decoder_->SetInputType(0, media_type.get(), 0); // No flags
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to set decoder's input type";
- return false;
- }
-
- return true;
-}
-
-bool MftH264Decoder::SetDecoderOutputMediaType(const GUID subtype) {
- DWORD i = 0;
- IMFMediaType* out_media_type;
- bool found = false;
- while (SUCCEEDED(decoder_->GetOutputAvailableType(0, i, &out_media_type))) {
- GUID out_subtype;
- HRESULT hr = out_media_type->GetGUID(MF_MT_SUBTYPE, &out_subtype);
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to GetGUID() on GetOutputAvailableType() " << i;
- out_media_type->Release();
- continue;
- }
- if (out_subtype == subtype) {
- hr = decoder_->SetOutputType(0, out_media_type, 0); // No flags
- hr = MFGetAttributeSize(out_media_type, MF_MT_FRAME_SIZE,
- reinterpret_cast<UINT32*>(&info_.stream_info.surface_width),
- reinterpret_cast<UINT32*>(&info_.stream_info.surface_height));
- config_.width = info_.stream_info.surface_width;
- config_.height = info_.stream_info.surface_height;
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to SetOutputType to |subtype| or obtain "
- << "width/height " << std::hex << hr;
- } else {
- out_media_type->Release();
- return true;
- }
- }
- i++;
- out_media_type->Release();
- }
- return false;
-}
-
-bool MftH264Decoder::SendMFTMessage(MFT_MESSAGE_TYPE msg) {
- HRESULT hr = decoder_->ProcessMessage(msg, NULL);
- return SUCCEEDED(hr);
-}
-
-// Prints out info about the input/output streams, gets the minimum buffer sizes
-// for input and output samples.
-// The MFT will not allocate buffer for neither input nor output, so we have
-// to do it ourselves and make sure they're the correct size.
-// Exception is when dxva is enabled, the decoder will allocate output.
-bool MftH264Decoder::GetStreamsInfoAndBufferReqs() {
- HRESULT hr = decoder_->GetInputStreamInfo(0, &input_stream_info_);
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to get input stream info";
- return false;
- }
- LOG(INFO) << "Input stream info: ";
- LOG(INFO) << "Max latency: " << input_stream_info_.hnsMaxLatency;
-
- // There should be three flags, one for requiring a whole frame be in a
- // single sample, one for requiring there be one buffer only in a single
- // sample, and one that specifies a fixed sample size. (as in cbSize)
- LOG(INFO) << "Flags: "
- << std::hex << std::showbase << input_stream_info_.dwFlags;
- CHECK_EQ(input_stream_info_.dwFlags, 0x7u);
- LOG(INFO) << "Min buffer size: " << input_stream_info_.cbSize;
- LOG(INFO) << "Max lookahead: " << input_stream_info_.cbMaxLookahead;
- LOG(INFO) << "Alignment: " << input_stream_info_.cbAlignment;
-
- hr = decoder_->GetOutputStreamInfo(0, &output_stream_info_);
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to get output stream info";
- return false;
- }
- LOG(INFO) << "Output stream info: ";
- // The flags here should be the same and mean the same thing, except when
- // DXVA is enabled, there is an extra 0x100 flag meaning decoder will
- // allocate its own sample.
- LOG(INFO) << "Flags: "
- << std::hex << std::showbase << output_stream_info_.dwFlags;
- CHECK_EQ(output_stream_info_.dwFlags, use_dxva_ ? 0x107u : 0x7u);
- LOG(INFO) << "Min buffer size: " << output_stream_info_.cbSize;
- LOG(INFO) << "Alignment: " << output_stream_info_.cbAlignment;
-
- return true;
-}
-
-bool MftH264Decoder::DoDecode() {
- if (state_ != kNormal && state_ != kEosDrain) {
- LOG(ERROR) << "DoDecode: not in normal or drain state";
- return false;
- }
- scoped_refptr<VideoFrame> frame;
- ScopedComPtr<IMFSample> output_sample;
- if (!use_dxva_) {
- output_sample.Attach(
- CreateEmptySampleWithBuffer(output_stream_info_.cbSize,
- output_stream_info_.cbAlignment));
- if (!output_sample.get()) {
- LOG(ERROR) << "GetSample: failed to create empty output sample";
- event_handler_->OnError();
- return false;
- }
- }
- MFT_OUTPUT_DATA_BUFFER output_data_buffer;
- memset(&output_data_buffer, 0, sizeof(output_data_buffer));
- output_data_buffer.dwStreamID = 0;
- output_data_buffer.pSample = output_sample;
-
- DWORD status;
- HRESULT hr = decoder_->ProcessOutput(0, // No flags
- 1, // # of out streams to pull from
- &output_data_buffer,
- &status);
-
- IMFCollection* events = output_data_buffer.pEvents;
- if (events != NULL) {
- LOG(INFO) << "Got events from ProcessOuput, but discarding";
- events->Release();
- }
-
- if (FAILED(hr)) {
- if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
- hr = SetDecoderOutputMediaType(ConvertVideoFrameFormatToGuid(
- info_.stream_info.surface_format));
- if (SUCCEEDED(hr)) {
- event_handler_->OnFormatChange(info_.stream_info);
- return true;
- } else {
- event_handler_->OnError();
- return false;
- }
- } else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
- if (state_ == kEosDrain) {
- // No more output from the decoder. Notify EOS and stop playback.
- scoped_refptr<VideoFrame> frame;
- VideoFrame::CreateEmptyFrame(&frame);
- event_handler_->ConsumeVideoFrame(frame);
- state_ = MftH264Decoder::kStopped;
- return false;
- }
- return true;
- } else {
- LOG(ERROR) << "Unhandled error in DoDecode()";
- state_ = MftH264Decoder::kStopped;
- event_handler_->OnError();
- return false;
- }
- }
-
- // We succeeded in getting an output sample.
- if (use_dxva_) {
- // For DXVA we didn't provide the sample, i.e. output_sample was NULL.
- output_sample.Attach(output_data_buffer.pSample);
- }
- if (!output_sample.get()) {
- LOG(ERROR) << "ProcessOutput succeeded, but did not get a sample back";
- event_handler_->OnError();
- return true;
- }
-
- int64 timestamp = 0, duration = 0;
- if (FAILED(output_sample->GetSampleTime(&timestamp)) ||
- FAILED(output_sample->GetSampleDuration(&duration))) {
- LOG(WARNING) << "Failed to get timestamp/duration from output";
- }
-
- // The duration and timestamps are in 100-ns units, so divide by 10
- // to convert to microseconds.
- timestamp /= 10;
- duration /= 10;
-
- // Sanity checks for checking if there is really something in the sample.
- DWORD buf_count;
- hr = output_sample->GetBufferCount(&buf_count);
- if (FAILED(hr) || buf_count != 1) {
- LOG(ERROR) << "Failed to get buffer count, or buffer count mismatch";
- return true;
- }
-
- ScopedComPtr<IMFMediaBuffer> output_buffer;
- hr = output_sample->GetBufferByIndex(0, output_buffer.Receive());
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to get buffer from sample";
- return true;
- }
-
-
-
- if (use_dxva_) {
- ScopedComPtr<IDirect3DSurface9> surface;
- hr = MFGetService(output_buffer, MR_BUFFER_SERVICE,
- IID_PPV_ARGS(surface.Receive()));
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to get surface from buffer";
- return true;
- }
-
- if (!frame.get()) {
- LOG(ERROR) << "Failed to allocate video frame for d3d texture";
- event_handler_->OnError();
- return true;
- }
-
- // The reference is now in the VideoFrame.
- surface.Detach();
- } else {
- // Not DXVA.
- VideoFrame::CreateFrame(info_.stream_info.surface_format,
- info_.stream_info.surface_width,
- info_.stream_info.surface_height,
- TimeDelta::FromMicroseconds(timestamp),
- TimeDelta::FromMicroseconds(duration),
- &frame);
- if (!frame.get()) {
- LOG(ERROR) << "Failed to allocate video frame for yuv plane";
- event_handler_->OnError();
- return true;
- }
- uint8* src_y;
- DWORD max_length, current_length;
- HRESULT hr = output_buffer->Lock(&src_y, &max_length, &current_length);
- if (FAILED(hr))
- return true;
- uint8* dst_y = static_cast<uint8*>(frame->data(VideoFrame::kYPlane));
-
- memcpy(dst_y, src_y, current_length);
- CHECK(SUCCEEDED(output_buffer->Unlock()));
- }
- // TODO(jiesun): non-System memory case
- event_handler_->ConsumeVideoFrame(frame);
- return true;
-}
-
-} // namespace media
diff --git a/media/mf/mft_h264_decoder.h b/media/mf/mft_h264_decoder.h
deleted file mode 100644
index 57c9e9f..0000000
--- a/media/mf/mft_h264_decoder.h
+++ /dev/null
@@ -1,97 +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.
-//
-// MFT H.264 decoder.
-
-#ifndef MEDIA_MF_MFT_H264_DECODER_H_
-#define MEDIA_MF_MFT_H264_DECODER_H_
-
-#include "build/build_config.h" // For OS_WIN.
-
-#if defined(OS_WIN)
-
-#include <d3d9.h>
-#include <dxva2api.h>
-#include <mfidl.h>
-
-#include "base/gtest_prod_util.h"
-#include "base/scoped_comptr_win.h"
-#include "media/video/video_decode_engine.h"
-
-class MessageLoop;
-
-namespace media {
-
-class MftH264Decoder : public media::VideoDecodeEngine {
- public:
- typedef enum {
- kUninitialized, // un-initialized.
- kNormal, // normal playing state.
- kFlushing, // upon received Flush(), before FlushDone()
- kEosDrain, // upon input EOS received.
- kStopped, // upon output EOS received.
- } State;
-
- explicit MftH264Decoder(bool use_dxva, HWND draw_window);
- ~MftH264Decoder();
- virtual void Initialize(MessageLoop* message_loop,
- VideoDecodeEngine::EventHandler* event_handler,
- VideoDecodeContext* context,
- const VideoCodecConfig& config);
- virtual void Uninitialize();
- virtual void Flush();
- virtual void Seek();
- virtual void ConsumeVideoSample(scoped_refptr<Buffer> buffer);
- virtual void ProduceVideoFrame(scoped_refptr<VideoFrame> frame);
-
- bool use_dxva() const { return use_dxva_; }
- IDirect3DDevice9* device() const { return device_.get(); }
- State state() const { return state_; }
-
- private:
- friend class MftH264DecoderTest;
- FRIEND_TEST_ALL_PREFIXES(MftH264DecoderTest, LibraryInit);
-
- // TODO(jiesun): Find a way to move all these to GpuVideoService..
- static bool StartupComLibraries();
- static void ShutdownComLibraries();
- bool CreateD3DDevManager();
-
- bool InitInternal();
- bool InitDecoder();
- bool CheckDecoderDxvaSupport();
- bool SetDecoderMediaTypes();
- bool SetDecoderInputMediaType();
- bool SetDecoderOutputMediaType(const GUID subtype);
- bool SendMFTMessage(MFT_MESSAGE_TYPE msg);
- bool GetStreamsInfoAndBufferReqs();
-
- bool DoDecode();
-
-
- bool use_dxva_;
-
- ScopedComPtr<IDirect3D9> d3d9_;
- ScopedComPtr<IDirect3DDevice9> device_;
- ScopedComPtr<IDirect3DDeviceManager9> device_manager_;
- HWND draw_window_;
- ScopedComPtr<IMFTransform> decoder_;
-
- MFT_INPUT_STREAM_INFO input_stream_info_;
- MFT_OUTPUT_STREAM_INFO output_stream_info_;
-
- State state_;
-
- VideoDecodeEngine::EventHandler* event_handler_;
- VideoCodecConfig config_;
- VideoCodecInfo info_;
-
- DISALLOW_COPY_AND_ASSIGN(MftH264Decoder);
-};
-
-} // namespace media
-
-#endif // defined(OS_WIN)
-
-#endif // MEDIA_MF_MFT_H264_DECODER_H_
diff --git a/media/mf/mft_h264_decoder_example.cc b/media/mf/mft_h264_decoder_example.cc
deleted file mode 100644
index b5b6b10..0000000
--- a/media/mf/mft_h264_decoder_example.cc
+++ /dev/null
@@ -1,421 +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.
-//
-// Demonstrates the use of MftH264Decoder.
-
-#include <cstdio>
-
-#include <string>
-
-#include <d3d9.h>
-#include <dxva2api.h>
-
-#include "base/at_exit.h"
-#include "base/command_line.h"
-#include "base/file_path.h"
-#include "base/logging.h"
-#include "base/message_loop.h"
-#include "base/scoped_comptr_win.h"
-#include "base/scoped_ptr.h"
-#include "base/time.h"
-#include "media/base/data_buffer.h"
-#include "media/base/media.h"
-#include "media/base/video_frame.h"
-#include "media/base/yuv_convert.h"
-#include "media/ffmpeg/ffmpeg_common.h"
-#include "media/ffmpeg/file_protocol.h"
-#include "media/mf/file_reader_util.h"
-#include "media/mf/mft_h264_decoder.h"
-
-using base::AtExitManager;
-using base::Time;
-using base::TimeDelta;
-using media::Buffer;
-using media::DataBuffer;
-using media::FFmpegFileReader;
-using media::MftH264Decoder;
-using media::VideoCodecConfig;
-using media::VideoCodecInfo;
-using media::VideoDecodeEngine;
-using media::VideoFrame;
-using media::VideoStreamInfo;
-
-namespace {
-
-const wchar_t* const kWindowClass = L"Chrome_H264_MFT";
-const wchar_t* const kWindowTitle = L"H264_MFT";
-const int kWindowStyleFlags = (WS_OVERLAPPEDWINDOW | WS_VISIBLE) &
- ~(WS_MAXIMIZEBOX | WS_THICKFRAME);
-
-void usage() {
- static char* usage_msg =
- "Usage: mft_h264_decoder [--enable-dxva] [--render] --input-file=FILE\n"
- "enable-dxva: Enables hardware accelerated decoding\n"
- "render: Render to window\n"
- "During rendering, press spacebar to skip forward at least 5 seconds.\n"
- "To display this message: mft_h264_decoder --help";
- fprintf(stderr, "%s\n", usage_msg);
-}
-
-static bool InitFFmpeg() {
- if (!media::InitializeMediaLibrary(FilePath()))
- return false;
- avcodec_init();
- av_register_all();
- av_register_protocol2(&kFFmpegFileProtocol, sizeof(kFFmpegFileProtocol));
- return true;
-}
-
-// Creates a window with the given width and height.
-// Returns: A handle to the window on success, NULL otherwise.
-static HWND CreateDrawWindow(int width, int height) {
- WNDCLASS window_class = {0};
- window_class.lpszClassName = kWindowClass;
- window_class.hInstance = NULL;
- window_class.hbrBackground = 0;
- window_class.lpfnWndProc = DefWindowProc;
- window_class.hCursor = 0;
-
- RegisterClass(&window_class);
-
- HWND window = CreateWindow(kWindowClass,
- kWindowTitle,
- kWindowStyleFlags,
- 100,
- 100,
- width,
- height,
- NULL,
- NULL,
- NULL,
- NULL);
- if (window == NULL) {
- LOG(ERROR) << "Failed to create window";
- return NULL;
- }
- RECT rect;
- rect.left = 0;
- rect.right = width;
- rect.top = 0;
- rect.bottom = height;
- AdjustWindowRect(&rect, kWindowStyleFlags, FALSE);
- MoveWindow(window, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
- TRUE);
- return window;
-}
-
-class WindowObserver : public base::MessagePumpWin::Observer {
- public:
- WindowObserver(FFmpegFileReader* reader, MftH264Decoder* decoder)
- : reader_(reader),
- decoder_(decoder) {
- }
-
- virtual void WillProcessMessage(const MSG& msg) {
- if (msg.message == WM_CHAR && msg.wParam == ' ') {
- // Seek forward 5 seconds.
- decoder_->Flush();
- reader_->SeekForward(5000000);
- }
- }
-
- virtual void DidProcessMessage(const MSG& msg) {
- }
-
- private:
- FFmpegFileReader* reader_;
- MftH264Decoder* decoder_;
-};
-
-class MftH264DecoderHandler
- : public VideoDecodeEngine::EventHandler,
- public base::RefCountedThreadSafe<MftH264DecoderHandler> {
- public:
- MftH264DecoderHandler() : frames_read_(0), frames_decoded_(0) {
- memset(&info_, 0, sizeof(info_));
- }
- virtual ~MftH264DecoderHandler() {}
- virtual void OnInitializeComplete(const VideoCodecInfo& info) {
- info_ = info;
- }
- virtual void OnUninitializeComplete() {
- }
- virtual void OnFlushComplete() {
- }
- virtual void OnSeekComplete() {}
- virtual void OnError() {}
- virtual void OnFormatChange(VideoStreamInfo stream_info) {
- info_.stream_info = stream_info;
- }
- virtual void ProduceVideoSample(scoped_refptr<Buffer> buffer) {
- if (reader_ && decoder_) {
- scoped_refptr<DataBuffer> input;
- reader_->Read(&input);
- if (!input->IsEndOfStream())
- frames_read_++;
- decoder_->ConsumeVideoSample(input);
- }
- }
- virtual void ConsumeVideoFrame(scoped_refptr<VideoFrame> frame) {
- if (frame.get()) {
- if (frame->format() != VideoFrame::EMPTY) {
- frames_decoded_++;
- }
- }
- }
- virtual void SetReader(FFmpegFileReader* reader) {
- reader_ = reader;
- }
- virtual void SetDecoder(MftH264Decoder* decoder) {
- decoder_= decoder;
- }
- virtual void DecodeSingleFrame() {
- scoped_refptr<VideoFrame> frame;
- decoder_->ProduceVideoFrame(frame);
- }
- virtual void Start() {
- while (decoder_->state() != MftH264Decoder::kStopped)
- DecodeSingleFrame();
- }
-
- VideoCodecInfo info_;
- int frames_read_;
- int frames_decoded_;
- FFmpegFileReader* reader_;
- MftH264Decoder* decoder_;
-};
-
-class RenderToWindowHandler : public MftH264DecoderHandler {
- public:
- RenderToWindowHandler(HWND window, MessageLoop* loop)
- : MftH264DecoderHandler(),
- window_(window),
- loop_(loop),
- has_output_(false) {
- }
- virtual ~RenderToWindowHandler() {}
- bool RenderSoftwareFrame(scoped_refptr<VideoFrame> frame) {
- int width = frame->width();
- int height = frame->height();
-
- // Assume height does not change.
- static uint8* rgb_frame = new uint8[height * frame->stride(0) * 4];
- uint8* frame_y = static_cast<uint8*>(frame->data(VideoFrame::kYPlane));
- uint8* frame_u = static_cast<uint8*>(frame->data(VideoFrame::kUPlane));
- uint8* frame_v = static_cast<uint8*>(frame->data(VideoFrame::kVPlane));
- media::ConvertYUVToRGB32(frame_y, frame_v, frame_u, rgb_frame,
- width, height,
- frame->stride(0), frame->stride(1),
- 4 * frame->stride(0), media::YV12);
- PAINTSTRUCT ps;
- InvalidateRect(window_, NULL, TRUE);
- HDC hdc = BeginPaint(window_, &ps);
- BITMAPINFOHEADER hdr;
- hdr.biSize = sizeof(BITMAPINFOHEADER);
- hdr.biWidth = width;
- hdr.biHeight = -height; // minus means top-down bitmap
- hdr.biPlanes = 1;
- hdr.biBitCount = 32;
- hdr.biCompression = BI_RGB; // no compression
- hdr.biSizeImage = 0;
- hdr.biXPelsPerMeter = 1;
- hdr.biYPelsPerMeter = 1;
- hdr.biClrUsed = 0;
- hdr.biClrImportant = 0;
- int rv = StretchDIBits(hdc, 0, 0, width, height, 0, 0, width, height,
- rgb_frame, reinterpret_cast<BITMAPINFO*>(&hdr),
- DIB_RGB_COLORS, SRCCOPY);
- EndPaint(window_, &ps);
- return rv != 0;
- }
- bool RenderD3dSurface(scoped_refptr<VideoFrame> frame) {
- ScopedComPtr<IDirect3DSurface9> surface;
- IDirect3DDevice9* device = decoder_->device();
- // TODO(hclam): Comment this since this file will be removed later.
- // surface.Attach(static_cast<IDirect3DSurface9*>(frame->d3d_texture(0)));
- HRESULT hr;
- hr = device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0),
- 1.0f, 0);
- if (FAILED(hr)) {
- LOG(ERROR) << "Device->Clear() failed";
- return false;
- }
- ScopedComPtr<IDirect3DSurface9> backbuffer;
- hr = device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
- backbuffer.Receive());
- if (FAILED(hr)) {
- LOG(ERROR) << "Device->GetBackBuffer() failed";
- return false;
- }
- hr = device->StretchRect(surface.get(), NULL, backbuffer.get(), NULL,
- D3DTEXF_NONE);
- if (FAILED(hr)) {
- LOG(ERROR) << "Device->StretchRect() failed";
- return false;
- }
- hr = device->Present(NULL, NULL, NULL, NULL);
- if (FAILED(hr)) {
- if (hr == E_FAIL) {
- LOG(WARNING) << "Present() returned E_FAIL";
- } else {
- static int frames_dropped = 0;
- LOG(ERROR) << "Device->Present() failed "
- << std::hex << std::showbase << hr;
- if (++frames_dropped == 10) {
- LOG(ERROR) << "Dropped too many frames, quitting";
- MessageLoopForUI::current()->QuitNow();
- return false;
- }
- }
- }
- return true;
- }
- virtual void ConsumeVideoFrame(scoped_refptr<VideoFrame> frame) {
- has_output_ = true;
- if (frame.get()) {
- if (frame->format() != VideoFrame::EMPTY) {
- frames_decoded_++;
- loop_->PostDelayedTask(
- FROM_HERE,
- NewRunnableMethod(this, &RenderToWindowHandler::DecodeSingleFrame),
- frame->GetDuration().InMilliseconds());
- bool success;
- if (decoder_->use_dxva()) {
- success = RenderD3dSurface(frame);
- } else {
- success = RenderSoftwareFrame(frame);
- }
- if (!success) {
- LOG(ERROR) << "Render failed";
- loop_->QuitNow();
- }
- } else { // if frame is type EMPTY, there will be no more frames.
- loop_->QuitNow();
- }
- }
- }
- virtual void DecodeSingleFrame() {
- if (decoder_->state() != MftH264Decoder::kStopped) {
- while (decoder_->state() != MftH264Decoder::kStopped && !has_output_) {
- scoped_refptr<VideoFrame> frame;
- decoder_->ProduceVideoFrame(frame);
- }
- if (decoder_->state() == MftH264Decoder::kStopped)
- loop_->QuitNow();
- has_output_ = false;
- } else {
- loop_->QuitNow();
- }
- }
- virtual void Start() {
- loop_->PostTask(
- FROM_HERE,
- NewRunnableMethod(this, &RenderToWindowHandler::DecodeSingleFrame));
- loop_->Run();
- }
-
- private:
- HWND window_;
- MessageLoop* loop_;
- bool has_output_;
-};
-
-static int Run(bool use_dxva, bool render, const std::string& input_file) {
- scoped_ptr<FFmpegFileReader> reader(new FFmpegFileReader(input_file));
- if (reader.get() == NULL || !reader->Initialize()) {
- LOG(ERROR) << "Failed to create/initialize reader";
- return -1;
- }
- int width = 0, height = 0;
- if (!reader->GetWidth(&width) || !reader->GetHeight(&height)) {
- LOG(WARNING) << "Failed to get width/height from reader";
- }
- VideoCodecConfig config;
- config.width = width;
- config.height = height;
- HWND window = NULL;
- if (use_dxva || render) {
- window = CreateDrawWindow(width, height);
- if (!render)
- ShowWindow(window, SW_HIDE);
- if (window == NULL) {
- LOG(ERROR) << "Failed to create window";
- return -1;
- }
- }
-
- scoped_ptr<MftH264Decoder> mft(new MftH264Decoder(use_dxva, window));
- if (!mft.get()) {
- LOG(ERROR) << "Failed to create MFT";
- return -1;
- }
-
- scoped_refptr<MftH264DecoderHandler> handler;
- if (render)
- handler = new RenderToWindowHandler(window, MessageLoop::current());
- else
- handler = new MftH264DecoderHandler();
- handler->SetDecoder(mft.get());
- handler->SetReader(reader.get());
- if (!handler.get()) {
- LOG(ERROR) << "Failed to create handler";
- return -1;
- }
-
- mft->Initialize(MessageLoop::current(), handler.get(), NULL, config);
- scoped_ptr<WindowObserver> observer;
- if (render) {
- observer.reset(new WindowObserver(reader.get(), mft.get()));
- MessageLoopForUI::current()->AddObserver(observer.get());
- }
-
- Time decode_start(Time::Now());
- handler->Start();
- TimeDelta decode_time = Time::Now() - decode_start;
-
- printf("All done, frames read: %d, frames decoded: %d\n",
- handler->frames_read_, handler->frames_decoded_);
- printf("Took %lldms\n", decode_time.InMilliseconds());
- if (window)
- DestroyWindow(window);
- return 0;
-}
-
-} // namespace
-
-int main(int argc, char** argv) {
- AtExitManager at_exit;
- MessageLoopForUI message_loop;
- CommandLine::Init(argc, argv);
- if (argc == 1) {
- fprintf(stderr, "Not enough arguments\n");
- usage();
- return -1;
- }
- const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
- if (cmd_line.HasSwitch("help")) {
- usage();
- return -1;
- }
- bool use_dxva = cmd_line.HasSwitch("enable-dxva");
- bool render = cmd_line.HasSwitch("render");
- std::string input_file = cmd_line.GetSwitchValueASCII("input-file");
- if (input_file.empty()) {
- fprintf(stderr, "No input file provided\n");
- usage();
- return -1;
- }
- printf("enable-dxva: %d\n", use_dxva);
- printf("render: %d\n", render);
- printf("input-file: %s\n", input_file.c_str());
-
- if (!InitFFmpeg()) {
- LOG(ERROR) << "InitFFMpeg() failed";
- return -1;
- }
- int ret = Run(use_dxva, render, input_file);
-
- printf("Done\n");
- return ret;
-}
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
diff --git a/media/mf/test/run_all_unittests.cc b/media/mf/test/run_all_unittests.cc
deleted file mode 100644
index 4126108..0000000
--- a/media/mf/test/run_all_unittests.cc
+++ /dev/null
@@ -1,26 +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/test/test_suite.h"
-#include "media/base/media.h"
-#include "media/ffmpeg/ffmpeg_common.h"
-#include "media/ffmpeg/file_protocol.h"
-
-static bool InitFFmpeg() {
- if (!media::InitializeMediaLibrary(FilePath()))
- return false;
- avcodec_init();
- av_register_all();
- av_register_protocol2(&kFFmpegFileProtocol, sizeof(kFFmpegFileProtocol));
- return true;
-}
-
-int main(int argc, char** argv) {
- if (!InitFFmpeg()) {
- fprintf(stderr, "Failed to init ffmpeg\n");
- return -1;
- }
- return TestSuite(argc, argv).Run();
-}