diff options
author | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-29 00:48:21 +0000 |
---|---|---|
committer | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-29 00:48:21 +0000 |
commit | 56af5803227e3e26de4cd234d8886394534f5f3c (patch) | |
tree | dd7318fe466cdf9038e0bf1dfdbe3260d5bf1f18 /media | |
parent | f164f48593d7c3d9ace978e00221e46423de1b65 (diff) | |
download | chromium_src-56af5803227e3e26de4cd234d8886394534f5f3c.zip chromium_src-56af5803227e3e26de4cd234d8886394534f5f3c.tar.gz chromium_src-56af5803227e3e26de4cd234d8886394534f5f3c.tar.bz2 |
Revert "This tool demonstrates the use of the Media Foundation H.264 decoder as a standalone Media Foundation Transform (MFT). See README for more information."
This reverts commit r54078, due to link failures.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54084 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/base/video_frame.h | 3 | ||||
-rw-r--r-- | media/media.gyp | 24 | ||||
-rwxr-xr-x | media/mf/README.chromium | 26 | ||||
-rwxr-xr-x | media/mf/file_reader_util.cc | 196 | ||||
-rwxr-xr-x | media/mf/file_reader_util.h | 68 | ||||
-rwxr-xr-x | media/mf/h264mft.cc | 633 | ||||
-rwxr-xr-x | media/mf/h264mft.h | 117 | ||||
-rwxr-xr-x | media/mf/main.cc | 299 |
8 files changed, 0 insertions, 1366 deletions
diff --git a/media/base/video_frame.h b/media/base/video_frame.h index cc54bba..a135bdf 100644 --- a/media/base/video_frame.h +++ b/media/base/video_frame.h @@ -33,7 +33,6 @@ class VideoFrame : public StreamSample { RGBA, // 32bpp RGBA packed 8:8:8:8 YV12, // 12bpp YVU planar 1x1 Y, 2x2 VU samples YV16, // 16bpp YVU planar 1x1 Y, 2x1 VU samples - NV12, // 12bpp YVU planar 1x1 Y, 2x2 UV interleaving samples EMPTY, // An empty frame. ASCII, // A frame with ASCII content. For testing only. }; @@ -42,8 +41,6 @@ class VideoFrame : public StreamSample { TYPE_SYSTEM_MEMORY, TYPE_OMXBUFFERHEAD, TYPE_EGL_IMAGE, - TYPE_MFBUFFER, - TYPE_DIRECT3DSURFACE }; public: diff --git a/media/media.gyp b/media/media.gyp index 454a038..dd5f189 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -416,30 +416,6 @@ }, }, }, - { - 'target_name': 'mft_h264_decoder', - 'type': 'executable', - 'dependencies': [ - 'media', - '../base/base.gyp:base', - '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg', - ], - 'include_dirs': [ - '..', - ], - 'sources': [ - 'mf/main.cc', - 'mf/h264mft.cc', - 'mf/h264mft.h', - 'mf/file_reader_util.cc', - 'mf/file_reader_util.h', - ], - 'msvs_settings': { - 'VCLinkerTool': { - 'SubSystem': '1', # Set /SUBSYSTEM:CONSOLE - }, - }, - }, ], }], ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', { diff --git a/media/mf/README.chromium b/media/mf/README.chromium deleted file mode 100755 index 2847e97..0000000 --- a/media/mf/README.chromium +++ /dev/null @@ -1,26 +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
-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 as a state machine, and the steps taken in each state.
-
-Requirements: Windows 7
-
-Note1: This tool currently does decoding only. There is no visible output
-besides the log entry containing state of the decoder at each input/output
-step.
-
-Note2: There is a mysterious 1-off decoded frame count when DXVA is enabled.
-
-Note3: 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/
-
-Note4: 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 100755 index cdb39aa..0000000 --- a/media/mf/file_reader_util.cc +++ /dev/null @@ -1,196 +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 <algorithm> - -#include "base/scoped_comptr_win.h" -#include "base/logging.h" -#include "media/ffmpeg/ffmpeg_common.h" -#include "media/filters/bitstream_converter.h" -#include "media/mf/h264mft.h" - -namespace media { - -////////////////////////////////////////////////////////////////////////////// -// FFmpegFileReader -FFmpegFileReader::FFmpegFileReader(const std::string& filename) - : filename_(filename), - format_context_(NULL), - codec_context_(NULL), - target_stream_(-1), - converter_(NULL), - end_of_stream_(false) { -} - -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(uint8** output, int* size) { - Read(output, size, NULL, NULL); -} - -void FFmpegFileReader::Read(uint8** output, int* size, int* duration, - int64* sample_time) { - if (!format_context_ || !codec_context_ || target_stream_ == -1) { - *size = 0; - *output = NULL; - return; - } - AVPacket packet; - bool found = false; - while (!found) { - int result = av_read_frame(format_context_, &packet); - if (result < 0) { - *output = NULL; - *size = 0; - end_of_stream_ = true; - return; - } - if (packet.stream_index == target_stream_) { - if (converter_.get() && !converter_->ConvertPacket(&packet)) { - LOG(ERROR) << "failed to convert AVPacket"; - } - *output = new uint8[packet.size]; - if (*output == NULL) { - LOG(ERROR) << "Failed to allocate buffer for annex b stream"; - *size = 0; - return; - } - *size = packet.size; - memcpy(*output, packet.data, packet.size); - if (duration) { - if (packet.duration == 0) { - LOG(WARNING) << "Packet duration not known"; - } - // This is in AVCodecContext::time_base units - *duration = packet.duration; - } - if (sample_time) { - if (packet.pts == AV_NOPTS_VALUE) { - LOG(ERROR) << "Packet presentation time not known"; - *sample_time = 0L; - } else { - // This is in AVCodecContext::time_base units - *sample_time = packet.pts; - } - } - found = true; - } - av_free_packet(&packet); - } -} - -bool FFmpegFileReader::GetFrameRate(int* num, int *denom) const { - if (!codec_context_) - return false; - *num = codec_context_->time_base.num; - *denom = 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::ConvertFFmpegTimeBaseTo100Ns( - 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 10,000 to convert it into units compatible with MF. - CHECK(codec_context_) << "Codec context needs to be initialized"; - return time_base_unit * 10000 * codec_context_->time_base.num / - codec_context_->time_base.den; -} - -} // namespace media diff --git a/media/mf/file_reader_util.h b/media/mf/file_reader_util.h deleted file mode 100755 index 71e79e2..0000000 --- a/media/mf/file_reader_util.h +++ /dev/null @@ -1,68 +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/scoped_handle.h" -#include "base/scoped_ptr.h" - -struct AVCodecContext; -struct AVFormatContext; - -namespace media { - -class BitstreamConverter; - -// 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(uint8** output, int* size) = 0; -}; - -class FFmpegFileReader : public FileReader { - public: - explicit FFmpegFileReader(const std::string& filename); - virtual ~FFmpegFileReader(); - virtual bool Initialize(); - virtual void Read(uint8** output, int* size); - - // Reads a video packet, converts it into Annex B stream, and allocates a - // buffer to |*output| and copies the contents into it. - void Read(uint8** output, int* size, int* duration, int64* sample_time); - 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 ConvertFFmpegTimeBaseTo100Ns(int64 time_base_unit) const; - bool end_of_stream() const { return end_of_stream_; } - - private: - std::string filename_; - AVFormatContext* format_context_; - AVCodecContext* codec_context_; - int target_stream_; - scoped_ptr<media::BitstreamConverter> converter_; - bool end_of_stream_; - - DISALLOW_COPY_AND_ASSIGN(FFmpegFileReader); -}; - -} // namespace media - -#endif // MEDIA_MF_FILE_READER_UTIL_H_ diff --git a/media/mf/h264mft.cc b/media/mf/h264mft.cc deleted file mode 100755 index bb7187d..0000000 --- a/media/mf/h264mft.cc +++ /dev/null @@ -1,633 +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/h264mft.h" - -#include <algorithm> -#include <string> - -#include <d3d9.h> -#include <evr.h> -#include <initguid.h> -#include <mfapi.h> -#include <mferror.h> -#include <mfidl.h> -#include <shlwapi.h> -#include <wmcodecdsp.h> - -#include "base/logging.h" -#include "base/scoped_comptr_win.h" -#include "media/base/video_frame.h" -#include "media/mf/file_reader_util.h" - -#pragma comment(lib, "dxva2.lib") -#pragma comment(lib, "d3d9.lib") -#pragma comment(lib, "mfuuid.lib") -#pragma comment(lib, "evr.lib") -#pragma comment(lib, "mfplat.lib") - -namespace media { - -// Returns Media Foundation's H.264 decoder as an MFT, or NULL if not found -// (e.g. Not using Windows 7) -static IMFTransform* GetH264Decoder() { - // Use __uuidof() to avoid linking to a library just for the CLSID. - IMFTransform* dec; - HRESULT hr = CoCreateInstance(__uuidof(CMSH264DecoderMFT), NULL, - CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&dec)); - if (FAILED(hr)) { - LOG(ERROR) << "CoCreateInstance failed " << std::hex << std::showbase << hr; - return NULL; - } - return dec; -} - -// 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|. -static IMFSample* CreateEmptySampleWithBuffer(int buffer_length) { - CHECK_GT(buffer_length, 0); - ScopedComPtr<IMFSample> sample; - sample.Attach(CreateEmptySample()); - if (sample.get() == NULL) - return NULL; - ScopedComPtr<IMFMediaBuffer> buffer; - HRESULT hr; - hr = MFCreateMemoryBuffer(buffer_length, 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. -static IMFSample* CreateInputSample(uint8* stream, int size, - int64 timestamp, int64 duration, - int min_size) { - CHECK(stream != NULL); - CHECK_GT(size, 0); - ScopedComPtr<IMFSample> sample; - sample.Attach(CreateEmptySampleWithBuffer(std::max(min_size, size))); - if (sample.get() == NULL) { - 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, ¤t_length); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to lock buffer"; - return NULL; - } - CHECK_EQ(static_cast<int>(current_length), 0); - 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(); -} - -// Public methods - -H264Mft::H264Mft(bool use_dxva) - : decoder_(NULL), - initialized_(false), - use_dxva_(use_dxva), - drain_message_sent_(false), - in_buffer_size_(0), - out_buffer_size_(0), - frames_read_(0), - frames_decoded_(0), - width_(0), - height_(0), - stride_(0) { -} - -H264Mft::~H264Mft() { -} - -bool H264Mft::Init(IDirect3DDeviceManager9* dev_manager, - int frame_rate_num, int frame_rate_denom, - int width, int height, - int aspect_num, int aspect_denom) { - if (initialized_) - return true; - if (!InitDecoder(dev_manager, frame_rate_num, frame_rate_denom, - width, height, aspect_num, aspect_denom)) - return false; - if (!GetStreamsInfoAndBufferReqs()) - return false; - if (!SendStartMessage()) - return false; - initialized_ = true; - return true; -} - -bool H264Mft::SendInput(uint8* data, int size, int64 timestamp, - int64 duration) { - CHECK(initialized_); - CHECK(data != NULL); - CHECK_GT(size, 0); - if (drain_message_sent_) { - LOG(ERROR) << "Drain message was already sent, but trying to send more " - "input to decoder"; - return false; - } - ScopedComPtr<IMFSample> sample; - sample.Attach(CreateInputSample(data, size, timestamp, duration, - in_buffer_size_)); - if (sample.get() == NULL) { - LOG(ERROR) << "Failed to convert input stream to sample"; - return false; - } - HRESULT hr = decoder_->ProcessInput(0, sample.get(), 0); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to ProcessInput, hr = " << std::hex << hr; - return false; - } - frames_read_++; - return true; -} - -static const char* const ProcessOutputStatusToCString(HRESULT hr) { - if (hr == MF_E_TRANSFORM_STREAM_CHANGE) - return "media stream change occurred, need to set output type"; - if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) - return "decoder needs more samples"; - else - return "unhandled error from ProcessOutput"; -} - -H264Mft::DecoderOutputState H264Mft::GetOutput( - scoped_refptr<VideoFrame>* decoded_frame) { - CHECK(initialized_); - CHECK(decoded_frame != NULL); - - ScopedComPtr<IMFSample> output_sample; - if (!use_dxva_) { - // If DXVA is enabled, the decoder will allocate the sample for us. - output_sample.Attach(CreateEmptySampleWithBuffer(out_buffer_size_)); - if (output_sample.get() == NULL) { - LOG(ERROR) << "GetSample: failed to create empty output sample"; - return kNoMemory; - } - } - MFT_OUTPUT_DATA_BUFFER output_data_buffer; - output_data_buffer.dwStreamID = 0; - output_data_buffer.pSample = output_sample; - output_data_buffer.dwStatus = 0; - output_data_buffer.pEvents = NULL; - DWORD status; - HRESULT hr; - hr = decoder_->ProcessOutput(0, // No flags - 1, // # of out streams to pull from - &output_data_buffer, - &status); - - // TODO(imcheng): Handle the events, if any. (No event is returned most of - // the time.) - IMFCollection* events = output_data_buffer.pEvents; - if (events != NULL) { - LOG(INFO) << "Got events from ProcessOuput, but discarding"; - events->Release(); - } - if (FAILED(hr)) { - LOG(INFO) << "ProcessOutput failed with status " << std::hex << hr - << ", meaning..." << ProcessOutputStatusToCString(hr); - if (hr == MF_E_TRANSFORM_STREAM_CHANGE) { - if (!SetDecoderOutputMediaType(MFVideoFormat_NV12)) { - LOG(ERROR) << "Failed to reset output type"; - return kResetOutputStreamFailed; - } else { - LOG(INFO) << "Reset output type done"; - return kResetOutputStreamOk; - } - } else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { - // At this point we have either read everything from file or we can - // still feed the decoder input. If we have read everything then we - // should've sent a drain message to the MFT. If the drain message is - // sent but it doesn't give out anymore output then we know the decoder - // has processed everything. - if (drain_message_sent_) { - LOG(INFO) << "Drain message was already sent + no output => done"; - return kNoMoreOutput; - } else { - return kNeedMoreInput; - } - } else { - return kUnspecifiedError; - } - } else { - // A decoded sample was successfully obtained. - LOG(INFO) << "Got a decoded sample from decoder"; - if (use_dxva_) { - // If dxva is enabled, we did not provide a sample to ProcessOutput, - // i.e. output_sample is NULL. - output_sample.Attach(output_data_buffer.pSample); - if (output_sample.get() == NULL) { - LOG(ERROR) << "Output sample using DXVA is NULL - ProcessOutput did " - << "not provide it!"; - return kOutputSampleError; - } - } - int64 timestamp, duration; - hr = output_sample->GetSampleTime(×tamp); - hr = output_sample->GetSampleDuration(&duration); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get sample duration or timestamp " - << std::hex << hr; - return kOutputSampleError; - } - - // 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)) { - LOG(ERROR) << "Failed to get buff count, hr = " << std::hex << hr; - return kOutputSampleError; - } - if (buf_count == 0) { - LOG(ERROR) << "buf_count is 0, dropping sample"; - return kOutputSampleError; - } - ScopedComPtr<IMFMediaBuffer> out_buffer; - hr = output_sample->GetBufferByIndex(0, out_buffer.Receive()); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get decoded output buffer"; - return kOutputSampleError; - } - - // To obtain the data, the caller should call the Lock() method instead - // of using the data field. - // In NV12, there are only 2 planes - the Y plane, and the interleaved UV - // plane. Both have the same strides. - uint8* null_data[2] = { NULL, NULL }; - int32 strides[2] = { stride_, stride_ }; - VideoFrame::CreateFrameExternal( - use_dxva_ ? VideoFrame::TYPE_DIRECT3DSURFACE : - VideoFrame::TYPE_MFBUFFER, - VideoFrame::NV12, - width_, - height_, - 2, - null_data, - strides, - base::TimeDelta::FromMicroseconds(timestamp), - base::TimeDelta::FromMicroseconds(duration), - out_buffer.Detach(), - decoded_frame); - CHECK(decoded_frame->get() != NULL); - frames_decoded_++; - return kOutputOk; - } -} - -bool H264Mft::SendDrainMessage() { - CHECK(initialized_); - if (drain_message_sent_) { - LOG(ERROR) << "Drain message was already sent before!"; - return false; - } - - // Send the drain message with no parameters. - HRESULT hr = decoder_->ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, NULL); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to send the drain message to decoder"; - return false; - } - drain_message_sent_ = true; - return true; -} - -// Private methods - -bool H264Mft::InitDecoder(IDirect3DDeviceManager9* dev_manager, - int frame_rate_num, int frame_rate_denom, - int width, int height, - int aspect_num, int aspect_denom) { - decoder_.Attach(GetH264Decoder()); - if (!decoder_.get()) - return false; - if (!CheckDecoderProperties()) - return false; - if (use_dxva_) { - if (!CheckDecoderDxvaSupport()) - return false; - if (!SetDecoderD3d9Manager(dev_manager)) - return false; - } - if (!SetDecoderMediaTypes(frame_rate_num, frame_rate_denom, - width, height, - aspect_num, aspect_denom)) { - return false; - } - return true; -} - -bool H264Mft::CheckDecoderProperties() { - DCHECK(decoder_.get()); - DWORD in_stream_count; - DWORD out_stream_count; - HRESULT hr; - hr = decoder_->GetStreamCount(&in_stream_count, &out_stream_count); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get stream count"; - return false; - } else { - LOG(INFO) << "Input stream count: " << in_stream_count << ", " - << "Output stream count: " << out_stream_count; - bool mismatch = false; - if (in_stream_count != 1) { - LOG(ERROR) << "Input stream count mismatch!"; - mismatch = true; - } - if (out_stream_count != 1) { - LOG(ERROR) << "Output stream count mismatch!"; - mismatch = true; - } - return !mismatch; - } -} - -bool H264Mft::CheckDecoderDxvaSupport() { - HRESULT hr; - ScopedComPtr<IMFAttributes> attributes; - 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)) { - LOG(ERROR) << "Failed to get DXVA attr, hr = " - << std::hex << std::showbase << hr - << "this might not be the right decoder."; - return false; - } - LOG(INFO) << "Support dxva? " << dxva; - if (!dxva) { - LOG(ERROR) << "Decoder does not support DXVA - this might not be the " - << "right decoder."; - return false; - } - return true; -} - -bool H264Mft::SetDecoderD3d9Manager(IDirect3DDeviceManager9* dev_manager) { - DCHECK(use_dxva_) << "SetDecoderD3d9Manager should only be called if DXVA is " - << "enabled"; - CHECK(dev_manager != NULL); - HRESULT hr; - hr = decoder_->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, - reinterpret_cast<ULONG_PTR>(dev_manager)); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to set D3D9 device to decoder"; - return false; - } - return true; -} - -bool H264Mft::SetDecoderMediaTypes(int frame_rate_num, int frame_rate_denom, - int width, int height, - int aspect_num, int aspect_denom) { - DCHECK(decoder_.get()); - if (!SetDecoderInputMediaType(frame_rate_num, frame_rate_denom, - width, height, - aspect_num, aspect_denom)) - return false; - if (!SetDecoderOutputMediaType(MFVideoFormat_NV12)) { - return false; - } - return true; -} - -bool H264Mft::SetDecoderInputMediaType(int frame_rate_num, int frame_rate_denom, - int width, int height, - int aspect_num, int aspect_denom) { - ScopedComPtr<IMFMediaType> media_type; - HRESULT hr; - hr = MFCreateMediaType(media_type.Receive()); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to create empty media type object"; - return NULL; - } - hr = media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); - if (FAILED(hr)) { - LOG(ERROR) << "SetGUID for major type failed"; - return NULL; - } - hr = media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); - if (FAILED(hr)) { - LOG(ERROR) << "SetGUID for subtype failed"; - return NULL; - } - - // Provide additional info to the decoder to avoid a format change during - // streaming. - if (frame_rate_num == 0 || frame_rate_denom == 0) { - hr = MFSetAttributeRatio(media_type.get(), MF_MT_FRAME_RATE, - frame_rate_num, frame_rate_denom); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to set frame rate"; - return NULL; - } - } - if (width == 0 || height == 0) { - hr = MFSetAttributeSize(media_type.get(), MF_MT_FRAME_SIZE, width, height); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to set frame size"; - return NULL; - } - } - - // TODO(imcheng): Not sure about this, but this is the recommended value by - // MSDN. - hr = media_type->SetUINT32(MF_MT_INTERLACE_MODE, - MFVideoInterlace_MixedInterlaceOrProgressive); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to set interlace mode"; - return NULL; - } - if (aspect_num == 0 || aspect_denom == 0) { - hr = MFSetAttributeRatio(media_type.get(), MF_MT_PIXEL_ASPECT_RATIO, - aspect_num, aspect_denom); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get aspect ratio"; - return NULL; - } - } - 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 H264Mft::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; - 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) { - LOG(INFO) << "|subtype| is at index " - << i << " in GetOutputAvailableType()"; - hr = decoder_->SetOutputType(0, out_media_type, 0); // No flags - hr = MFGetAttributeSize(out_media_type, MF_MT_FRAME_SIZE, - reinterpret_cast<UINT32*>(&width_), - reinterpret_cast<UINT32*>(&height_)); - hr = MFGetStrideForBitmapInfoHeader( - MFVideoFormat_NV12.Data1, - width_, - reinterpret_cast<LONG*>(&stride_)); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to SetOutputType to |subtype| or obtain " - << "width/height/stride " << std::hex << hr; - } else { - found = true; - out_media_type->Release(); - break; - } - } - i++; - out_media_type->Release(); - } - if (!found) { - LOG(ERROR) << "NV12 was not found in GetOutputAvailableType()"; - return false; - } - return true; -} - -bool H264Mft::SendStartMessage() { - HRESULT hr; - hr = decoder_->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, NULL); - if (FAILED(hr)) { - LOG(ERROR) << "Process start message failed, hr = " - << std::hex << std::showbase << hr; - return false; - } else { - LOG(INFO) << "Sent a message to decoder to indicate start of stream"; - return true; - } -} - -// 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 H264Mft::GetStreamsInfoAndBufferReqs() { - DCHECK(decoder_.get()); - HRESULT hr; - MFT_INPUT_STREAM_INFO input_stream_info; - 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(static_cast<int>(input_stream_info.dwFlags), 0x7); - LOG(INFO) << "Min buffer size: " << input_stream_info.cbSize; - LOG(INFO) << "Max lookahead: " << input_stream_info.cbMaxLookahead; - LOG(INFO) << "Alignment: " << input_stream_info.cbAlignment; - if (input_stream_info.cbAlignment > 0) { - LOG(WARNING) << "Warning: Decoder requires input to be aligned"; - } - in_buffer_size_ = input_stream_info.cbSize; - - MFT_OUTPUT_STREAM_INFO output_stream_info; - 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(static_cast<int>(output_stream_info.dwFlags), - use_dxva_ ? 0x107 : 0x7); - LOG(INFO) << "Min buffer size: " << output_stream_info.cbSize; - LOG(INFO) << "Alignment: " << output_stream_info.cbAlignment; - if (output_stream_info.cbAlignment > 0) { - LOG(WARNING) << "Warning: Decoder requires output to be aligned"; - } - out_buffer_size_ = output_stream_info.cbSize; - - return true; -} - -} // namespace media diff --git a/media/mf/h264mft.h b/media/mf/h264mft.h deleted file mode 100755 index 030bdec..0000000 --- a/media/mf/h264mft.h +++ /dev/null @@ -1,117 +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. -// -// Decodes H.264 Annex B streams using the Media Foundation H.264 decoder as -// a standalone Media Foundation Transform (MFT). -// Note: 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. - -#ifndef MEDIA_MF_H264MFT_H_ -#define MEDIA_MF_H264MFT_H_ - -#include <string> - -#include <mfidl.h> - -#include "base/basictypes.h" -#include "base/scoped_ptr.h" -#include "base/scoped_comptr_win.h" -#include "media/base/video_frame.h" - -struct IDirect3DDeviceManager9; -struct IMFSample; -struct IMFTransform; - -namespace media { - -// A decoder that takes samples of Annex B streams then outputs decoded frames. -class H264Mft { - public: - enum DecoderOutputState { - kOutputOk = 0, - kResetOutputStreamFailed, - kResetOutputStreamOk, - kNeedMoreInput, - kNoMoreOutput, - kUnspecifiedError, - kNoMemory, - kOutputSampleError - }; - explicit H264Mft(bool use_dxva); - ~H264Mft(); - - // Initializes the decoder. |dev_manager| is not required if the decoder does - // not use DXVA. - // If the other arguments are not known, leave them as 0. They can be - // provided to the decoder to try to avoid an initial output format change, - // but it is not necessary to have them. - bool Init(IDirect3DDeviceManager9* dev_manager, - int frame_rate_num, int frame_rate_denom, - int width, int height, - int aspect_num, int aspect_denom); - - // Sends an Annex B stream to the decoder. The times here should be given - // in 100ns units. This creates a IMFSample, copies the stream over to the - // sample, and sends the sample to the decoder. - // Returns: true if the sample was sent successfully. - bool SendInput(uint8* data, int size, int64 timestamp, int64 duration); - - // Tries to get an output sample from the decoder. - // Returns: status of the decoder, and if successful, a decoded sample. - DecoderOutputState GetOutput(scoped_refptr<VideoFrame>* decoded_frame); - - // Sends a drain message to the decoder to indicate no more input will be - // sent. SendInput() should not be called after calling this method. - // Returns: true if the drain message was sent successfully. - bool SendDrainMessage(); - - bool initialized() const { return initialized_; } - bool use_dxva() const { return use_dxva_; } - bool drain_message_sent() const { return drain_message_sent_; } - int in_buffer_size() const { return in_buffer_size_; } - int out_buffer_size() const { return out_buffer_size_; } - int frames_read() const { return frames_read_; } - int frames_decoded() const { return frames_decoded_; } - int width() const { return width_; } - int height() const { return height_; } - - private: - bool InitDecoder(IDirect3DDeviceManager9* dev_manager, - int frame_rate_num, int frame_rate_denom, - int width, int height, - int aspect_num, int aspect_denom); - bool CheckDecoderProperties(); - bool CheckDecoderDxvaSupport(); - bool SetDecoderD3d9Manager(IDirect3DDeviceManager9* dev_manager); - bool SetDecoderMediaTypes(int frame_rate_num, int frame_rate_denom, - int width, int height, - int aspect_num, int aspect_denom); - bool SetDecoderInputMediaType(int frame_rate_num, int frame_rate_denom, - int width, int height, - int aspect_num, int aspect_denom); - bool SetDecoderOutputMediaType(const GUID subtype); - bool SendStartMessage(); - bool GetStreamsInfoAndBufferReqs(); - - ScopedComPtr<IMFTransform> decoder_; - bool initialized_; - bool use_dxva_; - bool drain_message_sent_; - - // Minimum input and output buffer sizes as required by the decoder. - int in_buffer_size_; - int out_buffer_size_; - int frames_read_; - int frames_decoded_; - int width_; - int height_; - int stride_; - - DISALLOW_COPY_AND_ASSIGN(H264Mft); -}; - -} // namespace media - -#endif // MEDIA_MF_H264MFT_H_ diff --git a/media/mf/main.cc b/media/mf/main.cc deleted file mode 100755 index 93ca471..0000000 --- a/media/mf/main.cc +++ /dev/null @@ -1,299 +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 H264Mft. - -#include <d3d9.h> -#include <dxva2api.h> -#include <mfapi.h> - -#include "base/command_line.h" -#include "base/file_path.h" -#include "base/logging.h" -#include "base/scoped_comptr_win.h" -#include "base/scoped_ptr.h" -#include "base/time.h" -#include "media/base/media.h" -#include "media/ffmpeg/ffmpeg_common.h" -#include "media/ffmpeg/file_protocol.h" -#include "media/mf/file_reader_util.h" -#include "media/mf/h264mft.h" - -using media::FFmpegFileReader; -using media::H264Mft; -using media::VideoFrame; - -namespace { - -void usage() { - static char* usage_msg = - "Usage: h264mft [--enable-dxva] --input-file=FILE\n" - "enable-dxva: Enables hardware accelerated decoding\n" - "To display this message: h264mft --help"; - fprintf(stderr, "%s\n", usage_msg); -} - -static bool InitFFmpeg() { - if (!media::InitializeMediaLibrary(FilePath())) - return false; - avcodec_init(); - av_register_all(); - av_register_protocol(&kFFmpegFileProtocol); - return true; -} - -bool InitComLibraries() { - 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; -} - -void ShutdownComLibraries() { - HRESULT hr; - hr = MFShutdown(); - if (FAILED(hr)) { - LOG(WARNING) << "Warning: MF failed to shutdown"; - } - CoUninitialize(); -} - -IDirect3DDeviceManager9* CreateD3DDevManager(HWND video_window, - int width, - int height, - IDirect3D9** direct3d, - IDirect3DDevice9** device) { - CHECK(video_window != NULL); - CHECK(direct3d != NULL); - CHECK(device != NULL); - - ScopedComPtr<IDirect3DDeviceManager9> dev_manager; - ScopedComPtr<IDirect3D9> d3d; - d3d.Attach(Direct3DCreate9(D3D_SDK_VERSION)); - if (d3d == NULL) { - LOG(ERROR) << "Failed to create D3D9"; - return NULL; - } - D3DPRESENT_PARAMETERS present_params = {0}; - - present_params.BackBufferWidth = width; - present_params.BackBufferHeight = height; - present_params.BackBufferFormat = D3DFMT_UNKNOWN; - present_params.BackBufferCount = 1; - present_params.SwapEffect = D3DSWAPEFFECT_DISCARD; - present_params.hDeviceWindow = video_window; - present_params.Windowed = TRUE; - present_params.Flags = D3DPRESENTFLAG_VIDEO; - present_params.FullScreen_RefreshRateInHz = 0; - present_params.PresentationInterval = 0; - - ScopedComPtr<IDirect3DDevice9> temp_device; - - // D3DCREATE_HARDWARE_VERTEXPROCESSING specifies hardware vertex processing. - // (Is it even needed for just video decoding?) - HRESULT hr = d3d->CreateDevice(D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, - video_window, - D3DCREATE_HARDWARE_VERTEXPROCESSING, - &present_params, - temp_device.Receive()); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to create D3D Device"; - return NULL; - } - UINT dev_manager_reset_token = 0; - hr = DXVA2CreateDirect3DDeviceManager9(&dev_manager_reset_token, - dev_manager.Receive()); - if (FAILED(hr)) { - LOG(ERROR) << "Couldn't create D3D Device manager"; - return NULL; - } - hr = dev_manager->ResetDevice(temp_device.get(), dev_manager_reset_token); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to set device to device manager"; - return NULL; - } - *direct3d = d3d.Detach(); - *device = temp_device.Detach(); - return dev_manager.Detach(); -} - -// Example usage of how to get a decoded frame from the decoder. -bool GetDecodedSample(FFmpegFileReader* reader, H264Mft* decoder, - scoped_refptr<VideoFrame>* decoded_frame) { - // Keep feeding the MFT with inputs until it spits out an output. - for (;;) { - // First check if there is output. - H264Mft::DecoderOutputState state = decoder->GetOutput(decoded_frame); - if (state == H264Mft::kOutputOk) { - LOG(INFO) << "Got an output from decoder"; - return true; - } else if (state == H264Mft::kResetOutputStreamFailed) { - LOG(ERROR) << "Reset output stream failed, quitting"; - return false; - } else if (state == H264Mft::kResetOutputStreamOk) { - LOG(INFO) << "Reset output stream, try to get output again"; - continue; - } else if (state == H264Mft::kNeedMoreInput) { - LOG(INFO) << "Need more input"; - uint8* input_stream_dummy; - int size; - int duration; - int64 timestamp; - reader->Read(&input_stream_dummy, &size, &duration, ×tamp); - scoped_array<uint8> input_stream(input_stream_dummy); - if (input_stream.get() == NULL) { - LOG(INFO) << "No more input, sending drain message to decoder"; - if (!decoder->SendDrainMessage()) { - LOG(ERROR) << "Failed to send drain message, quitting"; - return false; - } else { - continue; // Try reading the rest of the drained outputs. - } - } else { - // We read an input stream, we can feed it into the decoder. - if (!decoder->SendInput(input_stream.get(), size, - reader->ConvertFFmpegTimeBaseTo100Ns(timestamp), - reader->ConvertFFmpegTimeBaseTo100Ns(duration))) { - LOG(ERROR) << "Failed to send input, dropping frame..."; - } - continue; // Try reading the output after attempting to send an input. - } - } else if (state == H264Mft::kNoMoreOutput) { - LOG(INFO) << "Decoder has processed everything, quitting"; - return false; - } else if (state == H264Mft::kUnspecifiedError) { - LOG(ERROR) << "Unknown error, quitting"; - return false; - } else if (state == H264Mft::kNoMemory) { - LOG(ERROR) << "Not enough memory for sample, quitting"; - return false; - } else if (state == H264Mft::kOutputSampleError) { - LOG(ERROR) << "Inconsistent sample, dropping..."; - continue; - } else { - NOTREACHED(); - } - } // for (;;) - NOTREACHED(); -} - -static void ReleaseOutputBuffer(VideoFrame* frame) { - if (frame->type() == VideoFrame::TYPE_MFBUFFER || - frame->type() == VideoFrame::TYPE_DIRECT3DSURFACE) { - static_cast<IMFMediaBuffer*>(frame->private_buffer())->Release(); - } else { - return; - } -} - -int Run(bool use_dxva, const std::string& input_file) { - scoped_ptr<FFmpegFileReader> reader(new FFmpegFileReader(input_file)); - if (reader.get() == NULL) { - LOG(ERROR) << "Failed to create reader"; - return -1; - } - if (!reader->Initialize()) { - LOG(ERROR) << "Failed to initialize reader"; - return -1; - } - int frame_rate_num = 0, frame_rate_denom = 0; - if (!reader->GetFrameRate(&frame_rate_num, &frame_rate_denom)) { - LOG(WARNING) << "Failed to get frame rate from reader"; - } - int width = 0, height = 0; - if (!reader->GetWidth(&width) || !reader->GetHeight(&height)) { - LOG(WARNING) << "Failed to get width/height from reader"; - } - int aspect_ratio_num = 0, aspect_ratio_denom = 0; - if (!reader->GetAspectRatio(&aspect_ratio_num, &aspect_ratio_denom)) { - LOG(WARNING) << "Failed to get aspect ratio from reader"; - } - ScopedComPtr<IDirect3D9> d3d9; - ScopedComPtr<IDirect3DDevice9> device; - ScopedComPtr<IDirect3DDeviceManager9> dev_manager; - if (use_dxva) { - dev_manager.Attach(CreateD3DDevManager(GetDesktopWindow(), - width, - height, - d3d9.Receive(), - device.Receive())); - if (dev_manager.get() == NULL) { - LOG(ERROR) << "Cannot create D3D9 manager"; - return -1; - } - } - scoped_ptr<H264Mft> mft(new H264Mft(use_dxva)); - if (mft.get() == NULL) { - LOG(ERROR) << "Failed to create MFT"; - return -1; - } - if (!mft->Init(dev_manager, frame_rate_num, frame_rate_denom, width, height, - aspect_ratio_num, aspect_ratio_denom)) { - LOG(ERROR) << "Failed to initialize mft"; - return -1; - } - base::TimeDelta decode_time; - while (true) { - // Do nothing with the sample except to let it go out of scope - scoped_refptr<VideoFrame> decoded_frame; - base::Time decode_start(base::Time::Now()); - if (!GetDecodedSample(reader.get(), mft.get(), &decoded_frame)) - break; - decode_time += base::Time::Now() - decode_start; - ReleaseOutputBuffer(decoded_frame.get()); - } - printf("All done, frames read: %d, frames decoded: %d\n", - mft->frames_read(), mft->frames_decoded()); - printf("Took %lldms\n", decode_time.InMilliseconds()); - return 0; -} - -} // namespace - -int main(int argc, char** argv) { - 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"); - 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("input-file: %s\n", input_file.c_str()); - - if (!InitFFmpeg()) { - LOG(ERROR) << "InitFFMpeg() failed"; - return -1; - } - if (!InitComLibraries()) { - LOG(ERROR) << "InitComLibraries() failed"; - return -1; - } - int ret = Run(use_dxva, input_file); - ShutdownComLibraries(); - printf("Done\n"); - return ret; -} |