diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-30 06:13:25 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-30 06:13:25 +0000 |
commit | f7ca36ad23d11a43fe7fec520cbe9cd7d51b76fe (patch) | |
tree | c3acb238d18f6f5352e72072ccc3689938822720 /media/tools | |
parent | 65acb404991f9ad0aee5cee1301805855373402b (diff) | |
download | chromium_src-f7ca36ad23d11a43fe7fec520cbe9cd7d51b76fe.zip chromium_src-f7ca36ad23d11a43fe7fec520cbe9cd7d51b76fe.tar.gz chromium_src-f7ca36ad23d11a43fe7fec520cbe9cd7d51b76fe.tar.bz2 |
Removing mfplayer and mfdecoder tools.
They've been unused for a year and are trivial to revert should we need them again.
Review URL: http://codereview.chromium.org/8083011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@103430 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/tools')
-rw-r--r-- | media/tools/mfdecoder/README.chromium | 46 | ||||
-rw-r--r-- | media/tools/mfdecoder/mfdecoder.cc | 323 | ||||
-rw-r--r-- | media/tools/mfdecoder/mfdecoder.h | 89 | ||||
-rw-r--r-- | media/tools/mfplayer/README.chromium | 27 | ||||
-rw-r--r-- | media/tools/mfplayer/mf_playback_main.cc | 326 | ||||
-rw-r--r-- | media/tools/mfplayer/mfplayer.cc | 823 | ||||
-rw-r--r-- | media/tools/mfplayer/mfplayer.h | 168 |
7 files changed, 0 insertions, 1802 deletions
diff --git a/media/tools/mfdecoder/README.chromium b/media/tools/mfdecoder/README.chromium deleted file mode 100644 index 422161d..0000000 --- a/media/tools/mfdecoder/README.chromium +++ /dev/null @@ -1,46 +0,0 @@ -This tool decodes a H.264 format video into YV12 frames and draws them onto -a window. - -The program uses Media Foundation to do much of the work. Specifically, it -uses the Source Reader (IMFSourceReader) to read from a file and the built-in -H.264 decoder (as an IMFTransform) to decode the video file into YV12 frames. -The decoding can be done with or without hardware acceleration. - -If decoding is done without hardware acceleration, then the YV12 frames are -converted into RGB using ConvertYUVToRGB32() provided in -media/base/yuv_convert.h. They are then drawn to a window using StretchDIBits() -provided in ui/gfx/gdi_util.h. - -If decoding is done with hardware acceleration, then the frames are obtained -from a D3D surface (IDirect3DSurface9). It is then drawn through calling -methods of a D3D device (IDirect3DDevice9) that is associated with the -video window that we created during initialization. - -The painting is done using a MessageLoop that posts paint tasks every 30ms -until the end of stream is reached. Thus the painting part acts like a -playback. - -Note: The current version uses a synchronous version of source reader. An -asynchronous version will likely to be more useful and have better -performance. - -Note2: The maximum resolution supported by Microsoft's H.264 decoder is -1920 by 1088 pixels. If you try to feed it a larger video, it will "fail -to determine frame size." This is an inherent limitation that cannot be fixed -unless a different decoder is used. - - -Requirements: Windows 7 - -usage: mfdecoder (-s|-h) (-d|-r|-f) input-file -flags: --s: Use software decoding --h: Uses hardware decoding - --d: Decode to YV12 as fast as possible, no rendering or color-space conversion --r: Render to window --f: Decode+render as fast as possible - -WARNING: Using both -h and -f, or opening too many windows with -h may lead to -driver crash / system instability. Realistically, you will never want to -do this unless you want to push the limits of the GPU ... diff --git a/media/tools/mfdecoder/mfdecoder.cc b/media/tools/mfdecoder/mfdecoder.cc deleted file mode 100644 index cef40d42..0000000 --- a/media/tools/mfdecoder/mfdecoder.cc +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright (c) 2011 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. - -#ifdef WINVER -#undef WINVER -#define WINVER 0x0601 // Windows 7 -#endif - -#include <d3d9.h> -#include <dxva2api.h> -#include <evr.h> -#include <mfapi.h> -#include <mferror.h> -#include <mfreadwrite.h> // depends on evr.h -#include <windows.h> - -#include "base/logging.h" -#include "base/win/scoped_comptr.h" -#include "media/tools/mfdecoder/mfdecoder.h" - -#pragma comment(lib, "shlwapi.lib") -#pragma comment(lib, "strmiids.lib") -#pragma comment(lib, "dxva2.lib") -#pragma comment(lib, "d3d9.lib") -#pragma comment(lib, "mfuuid.lib") -#pragma comment(lib, "mfplat.lib") -#pragma comment(lib, "mf.lib") -#pragma comment(lib, "evr.lib") -#pragma comment(lib, "mfreadwrite.lib") - -namespace media { - -MFDecoder::MFDecoder(bool use_dxva2) - : width_(0), - height_(0), - use_dxva2_(use_dxva2), - initialized_(false), - com_lib_initialized_(false), - mf_lib_initialized_(false), - reader_(NULL), - video_stream_index_(-1), - mfbuffer_stride_(0), - end_of_stream_(false) { -} - -MFDecoder::~MFDecoder() { - if (reader_) - reader_->Release(); - if (com_lib_initialized_) - CoUninitialize(); - if (mf_lib_initialized_) - MFShutdown(); -} - -bool MFDecoder::Init(const wchar_t* source_url, - IDirect3DDeviceManager9* dev_manager) { - if (initialized_) - return true; - if (source_url == NULL) { - LOG(ERROR) << "Init: source_url cannot be NULL"; - return false; - } - if (use_dxva2_ && dev_manager == NULL) { - LOG(ERROR) << "Init failed: DXVA2 specified, but no manager provided"; - return false; - } else if (!use_dxva2_ && dev_manager != NULL) { - LOG(WARNING) << "Init: Warning: DXVA2 not specified but manager is " - << "provided -- the manager will be ignored"; - dev_manager = NULL; - } - if (!InitLibraries()) - return false; - if (!InitSourceReader(source_url, dev_manager)) - return false; - - // By now, |reader_| should be initialized. - if (!SelectVideoStreamOnly()) - return false; - - // |video_stream_index_| should be pointing to the video stream now. - if (!InitVideoInfo(dev_manager)) - return false; - - initialized_ = true; - return true; -} - -IMFSample* MFDecoder::ReadVideoSample() { - CHECK(reader_ != NULL); - CHECK_GE(video_stream_index_, 0); - base::win::ScopedComPtr<IMFSample> video_sample; - DWORD actual_stream_index; - DWORD output_flags; - - // TODO(imcheng): Get timestamp back instead by passing in a timestamp pointer - // instead of NULL. - // TODO(imcheng): Read samples asynchronously and use callbacks. - HRESULT hr = reader_->ReadSample(video_stream_index_, - 0, // No flags. - &actual_stream_index, - &output_flags, - NULL, - video_sample.Receive()); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to read video sample"; - return NULL; - } else { - if (output_flags & MF_SOURCE_READERF_ERROR) { - LOG(ERROR) << "output_flag error while reading video sample"; - return NULL; - } - if (output_flags & MF_SOURCE_READERF_ENDOFSTREAM) { - VLOG(1) << "Video sample reading has reached the end of stream"; - end_of_stream_ = true; - return NULL; - } - if (static_cast<int>(actual_stream_index) != video_stream_index_) { - LOG(ERROR) << "Received sample from stream " << actual_stream_index - << " instead of intended video stream " << video_stream_index_; - return NULL; - } - if (video_sample.get() == NULL) - LOG(WARNING) << "Video sample is NULL and not at end of stream!"; - return video_sample.Detach(); - } -} - -// Private methods - -bool MFDecoder::InitLibraries() { - // TODO(imcheng): Move initialization to a singleton. - HRESULT hr; - hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); - if (FAILED(hr)) { - LOG(ERROR) << "CoInitializeEx failed during InitLibraries()"; - return false; - } - com_lib_initialized_ = true; - - hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); - if (FAILED(hr)) { - LOG(ERROR) << "MFStartup failed during InitLibraries()"; - CoUninitialize(); - com_lib_initialized_ = false; - return false; - } - mf_lib_initialized_ = true; - - return true; -} - -bool MFDecoder::InitSourceReader(const wchar_t* source_url, - IDirect3DDeviceManager9* dev_manager) { - CHECK(source_url != NULL); - base::win::ScopedComPtr<IMFAttributes> reader_attributes; - if (use_dxva2_) { - reader_attributes.Attach(GetDXVA2AttributesForSourceReader(dev_manager)); - if (reader_attributes == NULL) { - LOG(ERROR) << "Failed to create DXVA2 attributes for source reader"; - return false; - } - } - HRESULT hr = MFCreateSourceReaderFromURL(source_url, reader_attributes.get(), - &reader_); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to create source reader"; - return false; - } - VLOG(1) << "Source reader created"; - return true; -} - -IMFAttributes* MFDecoder::GetDXVA2AttributesForSourceReader( - IDirect3DDeviceManager9* dev_manager) { - if (!use_dxva2_) - return NULL; - CHECK(dev_manager != NULL); - base::win::ScopedComPtr<IMFAttributes> attributes; - - // Create an attribute store with an initial size of 2. - HRESULT hr = MFCreateAttributes(attributes.Receive(), 2); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to create DXVA2 attributes for source reader"; - return NULL; - } - hr = attributes->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, dev_manager); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to set D3D9 manager to attribute"; - return NULL; - } - hr = attributes->SetUINT32(MF_SOURCE_READER_DISABLE_DXVA, FALSE); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to set DISABLE_DXVA to false"; - return NULL; - } - return attributes.Detach(); -} - -bool MFDecoder::SelectVideoStreamOnly() { - CHECK(reader_ != NULL); - HRESULT hr; - for (DWORD stream_index = 0; ; stream_index++) { - base::win::ScopedComPtr<IMFMediaType> media_type; - hr = reader_->GetCurrentMediaType(stream_index, media_type.Receive()); - if (SUCCEEDED(hr)) { - GUID major_type; - hr = media_type->GetMajorType(&major_type); - if (FAILED(hr)) { - LOG(ERROR) << "Could not determine major type for stream " - << stream_index; - return false; - } - if (major_type != MFMediaType_Video) { - // Deselect any non-video streams. - hr = reader_->SetStreamSelection(stream_index, FALSE); - if (FAILED(hr)) { - LOG(ERROR) << "Could not deselect stream " << stream_index; - return false; - } - } else { - // Ensure that the video stream is selected. - hr = reader_->SetStreamSelection(stream_index, TRUE); - if (FAILED(hr)) { - LOG(ERROR) << "Could not select video stream " << stream_index; - return false; - } - video_stream_index_ = stream_index; - VLOG(1) << "Video stream is at " << video_stream_index_; - } - } else if (hr == MF_E_INVALIDSTREAMNUMBER) { - break; // No more streams, quit. - } else { - LOG(ERROR) << "Error occurred while getting stream " << stream_index; - return false; - } - } // end of for-loop - return video_stream_index_ >= 0; -} - -bool MFDecoder::InitVideoInfo(IDirect3DDeviceManager9* dev_manager) { - CHECK(reader_ != NULL); - CHECK_GE(video_stream_index_, 0); - base::win::ScopedComPtr<IMFMediaType> video_type; - HRESULT hr = reader_->GetCurrentMediaType(video_stream_index_, - video_type.Receive()); - if (FAILED(hr)) { - LOG(ERROR) << "InitVideoInfo: Failed to get video stream"; - return false; - } - GUID video_subtype; - hr = video_type->GetGUID(MF_MT_SUBTYPE, &video_subtype); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to determine video subtype"; - return false; - } - VLOG(1) << "Video subtype is " - << ((video_subtype == MFVideoFormat_H264) ? "" : "NOT ") << "H.264"; - hr = MFGetAttributeSize(video_type, MF_MT_FRAME_SIZE, - reinterpret_cast<UINT32*>(&width_), - reinterpret_cast<UINT32*>(&height_)); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to determine frame size"; - return false; - } - VLOG(1) << "Video width: " << width_ << ", height: " << height_; - - // Try to change to YV12 output format. - const GUID kOutputVideoSubtype = MFVideoFormat_YV12; - base::win::ScopedComPtr<IMFMediaType> output_video_format; - hr = MFCreateMediaType(output_video_format.Receive()); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to create a IMFMediaType object for video output"; - return false; - } - if (SUCCEEDED(hr)) - hr = output_video_format->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); - if (SUCCEEDED(hr)) - hr = output_video_format->SetGUID(MF_MT_SUBTYPE, kOutputVideoSubtype); - if (SUCCEEDED(hr)) { - hr = MFSetAttributeSize(output_video_format, MF_MT_FRAME_SIZE, width_, - height_); - } - if (SUCCEEDED(hr)) { - hr = reader_->SetCurrentMediaType(video_stream_index_, - NULL, // Reserved. - output_video_format); - } - if (SUCCEEDED(hr)) { - hr = MFGetStrideForBitmapInfoHeader( - kOutputVideoSubtype.Data1, - width_, - reinterpret_cast<LONG*>(&mfbuffer_stride_)); - } - if (FAILED(hr)) { - LOG(ERROR) << "Failed to change output video format and determine stride"; - return false; - } - VLOG(1) << "IMFMediaBuffer stride: " << mfbuffer_stride_; - - // Send a message to the decoder to tell it to use DXVA2. - if (use_dxva2_) { - // Call GetServiceForStream to get the interface to the video decoder. - base::win::ScopedComPtr<IMFTransform> video_decoder; - hr = reader_->GetServiceForStream(video_stream_index_, GUID_NULL, - IID_PPV_ARGS(video_decoder.Receive())); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to obtain interface to decoder"; - return false; - } else { - hr = video_decoder->ProcessMessage( - MFT_MESSAGE_SET_D3D_MANAGER, - reinterpret_cast<ULONG_PTR>(dev_manager)); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to send DXVA message to decoder"; - return false; - } - } - } - return true; -} - -} // namespace media diff --git a/media/tools/mfdecoder/mfdecoder.h b/media/tools/mfdecoder/mfdecoder.h deleted file mode 100644 index e280f9c..0000000 --- a/media/tools/mfdecoder/mfdecoder.h +++ /dev/null @@ -1,89 +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. - -#ifndef MEDIA_TOOLS_MFDECODER_MFDECODER_H_ -#define MEDIA_TOOLS_MFDECODER_MFDECODER_H_ - -#include "base/basictypes.h" - -struct IDirect3DDeviceManager9; -struct IMFAttributes; -struct IMFSample; -struct IMFSourceReader; - -namespace media { - -class MFDecoder { - public: - explicit MFDecoder(bool use_dxva2); - ~MFDecoder(); - - // This method is to be called after the constructor. This method - // creates a source reader with the given URL, and initializes the member - // variables that are related to the video, such as the dimensions of the - // video, stride, index of video stream, etc. - // If DXVA2 was specified in the constructor, then the given device manager - // is passed into the source reader so that it can do hardware accelerated - // decoding. - // Returns: true on success. - bool Init(const wchar_t* source_url, IDirect3DDeviceManager9* dev_manager); - int width() const { return width_; } - int height() const { return height_; } - bool use_dxva2() const { return use_dxva2_; } - bool initialized() const { return initialized_; } - int mfbuffer_stride() const { return mfbuffer_stride_; } - bool end_of_stream() const { return end_of_stream_; } - - // Reads a single video sample. If end of stream is reached, |end_of_stream_| - // will be set to true. - // Returns: Pointer to a IMFSample on success, NULL otherwise. Caller is - // responsible for releasing the sample. - IMFSample* ReadVideoSample(); - - private: - // Initializes the COM and MF libraries for this decoder. The two libraries - // are either both initialized, or both uninitialized. - // Returns: true if both libraries were successfully initialized. - bool InitLibraries(); - - // Initializes the source reader with the given URL, and device manager if - // DXVA2 is enabled on the decoder. - // Returns: true on success. - bool InitSourceReader(const wchar_t* source_url, - IDirect3DDeviceManager9* dev_manager); - - // Called by InitSourceReader() if DXVA2 is to be used. Creates an attribute - // store that can be passed to the source reader constructor. - // Caller is responsible for releasing the attribute object. - // Returns: pointer to an IMFAttributes object if successful, NULL otherwise. - IMFAttributes* GetDXVA2AttributesForSourceReader( - IDirect3DDeviceManager9* dev_manager); - - // Deselects any non-video streams, ensures the video stream is selected, and - // initializes |video_stream_index_| to that video stream. - // Returns: true on success. - bool SelectVideoStreamOnly(); - - // Obtains information about the video (height, width, etc.) and sets the - // output format to YV12. - // Returns: true on success. - bool InitVideoInfo(IDirect3DDeviceManager9* dev_manager); - - int width_; - int height_; - bool use_dxva2_; - bool initialized_; - bool com_lib_initialized_; - bool mf_lib_initialized_; - IMFSourceReader* reader_; - int video_stream_index_; - int mfbuffer_stride_; - bool end_of_stream_; - - DISALLOW_COPY_AND_ASSIGN(MFDecoder); -}; - -} // namespace media - -#endif // MEDIA_TOOLS_MFDECODER_MFDECODER_H_ diff --git a/media/tools/mfplayer/README.chromium b/media/tools/mfplayer/README.chromium deleted file mode 100644 index 18a4517..0000000 --- a/media/tools/mfplayer/README.chromium +++ /dev/null @@ -1,27 +0,0 @@ -This sample demonstrates how to play clear content in Media Foundation. The -code is taken and modified from Media Foundation sample code website: -http://code.msdn.microsoft.com/mediafoundation - -Requirements: Windows 7 - -6/28/2010 - Version 1 -6/29/2010 - Added option for saving file in .mp4 format -7/1/2010 - Changed return types of public methods, disabled audio since the -purpose is to use Media Foundation's video capabilities only. - -Usage: mf_playback.exe (-r|-f) (-s|-h) input-file [output-file] -There are two flags that needs to be specified, plus an input file. - -Flag 1: --r: Render to window. This is the playback mode. During playback mode, press - spacebar to switch between play/pause. --f: Transcode. A media file is transcoded into mp4 format (H.264/AAC). An - output file needs to be specified as the argument after input file. - -Flag 2: --s: Software decoding. --h: Hardware decoding using DXVA2. Not implemented yet. - - -Todos: - - Add flags to support hardware decoding diff --git a/media/tools/mfplayer/mf_playback_main.cc b/media/tools/mfplayer/mf_playback_main.cc deleted file mode 100644 index 3ce897c..0000000 --- a/media/tools/mfplayer/mf_playback_main.cc +++ /dev/null @@ -1,326 +0,0 @@ -// Copyright (c) 2011 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. - -// This header is placed first to avoid compiler warning. -#include "media/tools/mfplayer/mfplayer.h" - -#include <mfapi.h> -#define STRSAFE_NO_DEPRECATE -#include <strsafe.h> - -#include <cassert> - -namespace mfplayer { - -const wchar_t g_window_title[] = L"MFBasicPlayback"; -const wchar_t g_window_class[] = L"Chrome_MFBasicPlayback"; - -// True if there is no video playing, so we have to paint the window ourselves. -bool g_repaint_client = true; - -// Global player object. -// Note: After WM_CREATE is processed, g_main_player remains valid until the -// window is destroyed. -MFPlayer* g_main_player = NULL; - -wchar_t* g_input_file_name = NULL; - -void Usage() { - fprintf(stderr, "Usage: mf_playback (-r|-f) (-h|-s) file [out-file]\n"); -} - -void UpdateUI(HWND window_handle, MFPlayer::PlayerState state) { - assert(g_main_player != NULL); - - bool playback_started = state == MFPlayer::STARTED || - state == MFPlayer::PAUSED; - g_repaint_client = !playback_started || !g_main_player->HasVideo(); -} - -// Shows a message box with an error message. -void NotifyError(HWND window_handle, PCWSTR error_message, HRESULT error_code) { - const size_t kMessageLen = 512; - wchar_t message[kMessageLen]; - - HRESULT hr = StringCchPrintf(message, kMessageLen, L"%s (HRESULT = 0x%X)", - error_message, error_code); - if (SUCCEEDED(hr)) - MessageBox(window_handle, message, NULL, MB_OK | MB_ICONERROR); -} - -// Converts a ANSI string to an Unicode string. It is caller's responsibility -// to call delete[] on the returned string when it is no longer being used. -int ConvertANSIStringToUnicode(const char* source, wchar_t** dest) { - DWORD string_length = MultiByteToWideChar(CP_ACP, 0, source, -1, NULL, 0); - if (string_length == 0) { - fprintf(stderr, "Error getting size of ansi string: %s\n", source); - return 1; - } - *dest = new wchar_t[string_length]; - if (*dest == NULL) { - fprintf(stderr, "Error allocating unicode string buffer\n"); - return 1; - } - if (MultiByteToWideChar(CP_ACP, 0, source, string_length, *dest, - string_length) == 0) { - fprintf(stderr, "Error converting ansi string to unicode: %#X", - GetLastError()); - return 1; - } - return 0; -} - -// Callback when window is created. It has been modified to both create -// the media player and starts playing the provided file in one go. -LRESULT OnCreateWindow(HWND window_handle) { - // Initialize the player object. - HRESULT hr = MFPlayer::CreateInstance(window_handle, window_handle, - true, &g_main_player); - if (SUCCEEDED(hr)) { - UpdateUI(window_handle, MFPlayer::CLOSED); - } else { - NotifyError(NULL, L"Could not initialize the player object.", hr); - return -1; // Destroy the window - } - - // Play the video - assert(g_input_file_name != NULL); - - // No output URL, just the window. - hr = g_main_player->OpenURL(g_input_file_name, NULL); - if (SUCCEEDED(hr)) { - UpdateUI(window_handle, MFPlayer::OPEN_PENDING); - return 0; - } else { - _fwprintf_p(stderr, L"Fatal error: cannot open file %s\n", - g_input_file_name); - return -1; // Destroy the window - } -} - -void OnPaint(HWND window_handle) { - if (g_repaint_client) { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(window_handle, &ps); - // The video is not playing, so we must paint the application window. - RECT rc; - GetClientRect(window_handle, &rc); - FillRect(hdc, &rc, reinterpret_cast<HBRUSH>(COLOR_WINDOW)); - EndPaint(window_handle, &ps); - } else { - // Video is playing. Ask the player to repaint. - g_main_player->Repaint(); - } -} - -void OnKeyPress(WPARAM key) { - switch (key) { - // Space key toggles between running and paused. - case VK_SPACE: - if (g_main_player->state() == MFPlayer::STARTED) - g_main_player->Pause(); - else if (g_main_player->state() == MFPlayer::PAUSED) - g_main_player->Play(); - break; - } -} - -void OnPlayerEvent(HWND window_handle, WPARAM event) { - HRESULT hr = S_OK; - - hr = g_main_player->HandleEvent(event); - if (FAILED(hr)) - NotifyError(window_handle, L"An error occurred.", hr); - UpdateUI(window_handle, g_main_player->state()); -} - -LRESULT CALLBACK CallbackProc(HWND window_handle, UINT message, WPARAM w_param, - LPARAM l_param) { - switch (message) { - case WM_CREATE: - return OnCreateWindow(window_handle); - case WM_PAINT: - OnPaint(window_handle); - break; - case WM_SIZE: - g_main_player->ResizeVideo(LOWORD(l_param), HIWORD(l_param)); - break; - case WM_ERASEBKGND: - // Suppress window erasing, to reduce flickering while the video is - // playing. - return 1; - case WM_DESTROY: - PostQuitMessage(0); - break; - case WM_CHAR: - OnKeyPress(w_param); - break; - case MFPlayer::WM_APP_PLAYER_EVENT: - OnPlayerEvent(window_handle, w_param); - break; - default: - return DefWindowProc(window_handle, message, w_param, l_param); - } - return 0; -} - -// Creates a window for doing playback. -bool InitInstance() { - HWND window_handle; - WNDCLASSEX window_class_info; - - // Register the window class. - ZeroMemory(&window_class_info, sizeof(WNDCLASSEX)); - window_class_info.cbSize = sizeof(WNDCLASSEX); - window_class_info.style = CS_HREDRAW | CS_VREDRAW; - window_class_info.lpfnWndProc = CallbackProc; - window_class_info.hInstance = NULL; - window_class_info.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW+1); - window_class_info.lpszMenuName = NULL; - window_class_info.lpszClassName = g_window_class; - - if (RegisterClassEx(&window_class_info) == 0) - return false; - - // Create the application window. - window_handle = CreateWindow(g_window_class, g_window_title, - WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, - CW_USEDEFAULT, 0, NULL, NULL, NULL, NULL); - if (window_handle == 0) { - fprintf(stderr, "Cannot create window\n"); - return false; - } - - ShowWindow(window_handle, SW_SHOW); - UpdateWindow(window_handle); - return true; -} - -int RunRendererApp() { - if (!InitInstance()) { - fprintf(stderr, "Could not initialize the application\n"); - return 1; - } - MSG message; - ZeroMemory(&message, sizeof(message)); - // Main message loop. - while (GetMessage(&message, NULL, 0, 0)) { - TranslateMessage(&message); - DispatchMessage(&message); - } - return 0; -} - -int RunTranscoderApp(const char* output_file_name) { - HRESULT hr; - int ret = 0; - - // In here, we do not use any windows - just use the media player as a - // transcoder. - hr = MFPlayer::CreateInstance(NULL, NULL, false, &g_main_player); - if (FAILED(hr)) { - fprintf(stderr, "Transcoder app: Could not create player\n"); - return 1; - } - wchar_t* output_file_name_wchar = NULL; - if (ConvertANSIStringToUnicode(output_file_name, - &output_file_name_wchar) != 0) { - fprintf(stderr, "Fatal error while converting output_file_name\n"); - return 1; - } - hr = g_main_player->OpenURL(g_input_file_name, output_file_name_wchar); - if (FAILED(hr)) { - fprintf(stderr, "Failed to open URL and configure transcoder profile\n"); - ret = 1; - goto cleanup; - } - fprintf(stderr, "Transcode starting now, writing to %s\n", output_file_name); - hr = g_main_player->Transcode(); - if (FAILED(hr)) { - fprintf(stderr, "Transcode failed\n"); - ret = 1; - goto cleanup; - } - if (SUCCEEDED(hr)) - fprintf(stderr, "Transcode successful\n"); - cleanup: - delete[] output_file_name_wchar; - return ret; -} - -int main2(int argc, char** argv) { - bool use_renderer_sink; - bool enable_dxva2; - if (argc < 4) { - Usage(); - return 1; - } - if (strcmp(argv[1], "-r") == 0) { - use_renderer_sink = true; - } else if (strcmp(argv[1], "-f") == 0) { - use_renderer_sink = false; - if (argc < 5) { - fprintf(stderr, "Archive sink specified but out-file missing\n"); - Usage(); - return 1; - } - } else { - fprintf(stderr, "Unknown option '%s'\n", argv[1]); - Usage(); - return 1; - } - if (strcmp(argv[2], "-h") == 0) { - enable_dxva2 = true; - } else if (strcmp(argv[2], "-s") == 0) { - enable_dxva2 = false; - } else { - fprintf(stderr, "Unknown option '%s'\n", argv[2]); - Usage(); - return 1; - } - - // TODO(imcheng): implement the option for hardware acceleration - fprintf(stderr, "use_renderer_sink: %s\n", - use_renderer_sink ? "TRUE" : "FALSE"); - fprintf(stderr, "enable_dxva2: %s\n", enable_dxva2 ? "TRUE" : "FALSE"); - - HRESULT hr; - // Startup is moved from object creation to main method. - hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); - if (FAILED(hr)) { - fprintf(stderr, "MFStartup failed: %#X", hr); - return 1; - } - - // Note: This function allocates space for g_input_file_name on the heap, so - // remember to free it at the end. - if (ConvertANSIStringToUnicode(argv[3], &g_input_file_name) != 0) { - fprintf(stderr, "Fatal error while converting g_input_file_name\n"); - return 1; - } - _fwprintf_p(stderr, L"Input file: %s\n", g_input_file_name); - int retval; - if (use_renderer_sink) - retval = RunRendererApp(); - else - retval = RunTranscoderApp(argv[4]); - - // Clean up. - if (g_main_player) { - g_main_player->Shutdown(); - g_main_player->Release(); - } - MFShutdown(); - delete[] g_input_file_name; - - printf("Terminated\n"); - return retval; -} - -} // namespace mfplayer - - -int main(int argc, char** argv) { - return mfplayer::main2(argc, argv); -} diff --git a/media/tools/mfplayer/mfplayer.cc b/media/tools/mfplayer/mfplayer.cc deleted file mode 100644 index 7ef51e1..0000000 --- a/media/tools/mfplayer/mfplayer.cc +++ /dev/null @@ -1,823 +0,0 @@ -// Copyright (c) 2011 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/tools/mfplayer/mfplayer.h" - -#include <mfapi.h> -#include <mferror.h> -#include <shlwapi.h> - -#include <cassert> -#include <cstdio> - -template <class T> -static void SafeRelease(T** pptr) { - if (pptr && *pptr) { - (*pptr)->Release(); - *pptr = NULL; - } -} - -static HRESULT ProbeTopology(IMFMediaEvent* event, - IMFTopology** topology_ptr) { - HRESULT hr = S_OK; - PROPVARIANT var; - PropVariantInit(&var); - hr = event->GetValue(&var); - if (SUCCEEDED(hr)) { - if (var.vt != VT_UNKNOWN) - hr = E_UNEXPECTED; - } - if (SUCCEEDED(hr)) - hr = var.punkVal->QueryInterface(IID_PPV_ARGS(topology_ptr)); - PropVariantClear(&var); - return hr; -} - -namespace mfplayer { - -// Public methods - -bool MFPlayer::CreateInstance(HWND video_window, HWND event_window, - bool render_to_window, MFPlayer** player) { - if (!player) - return false; - - HRESULT hr = S_OK; - MFPlayer* temp_player = new MFPlayer(video_window, event_window, - render_to_window); - if (!temp_player) - return false; - - hr = temp_player->Initialize(); - if (SUCCEEDED(hr)) { - *player = temp_player; - (*player)->AddRef(); - } - // If above succeeded, then ref count is now 2, so SafeRelease won't delete - // the object. - SafeRelease(&temp_player); - return SUCCEEDED(hr); -} - -// Override IUnknown -HRESULT MFPlayer::QueryInterface(REFIID id, void** object_ptr) { - static const QITAB qit[] = { QITABENT(MFPlayer, IMFAsyncCallback), {0}}; - return QISearch(this, qit, id, object_ptr); -} - -ULONG MFPlayer::AddRef() { - return InterlockedIncrement(&ref_count_); -} - -ULONG MFPlayer::Release() { - ULONG count = InterlockedDecrement(&ref_count_); - if (count == 0) - delete this; - return count; -} - -// IMFAsyncCallback implementation -// Callback for asynchronous BeginGetEvent method. -HRESULT MFPlayer::Invoke(IMFAsyncResult* result) { - IMFMediaEvent* event = NULL; - MediaEventType event_type = MEUnknown; - - HRESULT hr = session_->EndGetEvent(result, &event); - if (FAILED(hr)) - goto done; - hr = event->GetType(&event_type); - if (FAILED(hr)) - goto done; - - // |session_|->Close() queues an event of this type. - // If the session is closed, the application is waiting on the event - // handle. Also, do not request any more events from the session. - if (event_type == MESessionClosed) { - SetEvent(close_event_); - } else { - // For all other events, ask the media session for the - // next event in the queue. - hr = session_->BeginGetEvent(this, NULL); - if (FAILED(hr)) - goto done; - } - // For most events, post the event as a private window message to the - // application. This lets the application process the event on its main - // thread. - - // However, if a call to IMFMediaSession::Close is pending, it means the - // application is waiting on the m_hCloseEvent event handle. (Blocking - // call.) In that case, we simply discard the event. - - // When IMFMediaSession::Close is called, MESessionClosed is NOT - // necessarily the next event that we will receive. We may receive any - // number of other events before receiving MESessionClosed. - if (state_ != CLOSING) { - event->AddRef(); - // Post this event onto the event_window_'s queue. When an event is - // received, the app calls MFPlayer::HandleEvent() to handle the event. - PostMessage(event_window_, WM_APP_PLAYER_EVENT, (WPARAM)event, NULL); - } - done: - return S_OK; -} - -// This method does the following: -// 1. Create a new media session. -// 2. Create the media source. -// 3. Create the topology. -// 4. Queue the topology [asynchronous] -// 5. Start playback [asynchronous - does not happen in this method.] -bool MFPlayer::OpenURL(const WCHAR* in_url, const WCHAR* out_url) { - IMFTopology* topology = NULL; - HRESULT hr; - - // Initializes |session_|. - hr = CreateSession(); - if (FAILED(hr)) - goto done; - // Initializes |source_|. - hr = CreateMediaSource(in_url); - if (FAILED(hr)) - goto done; - if (render_to_window_) { - // Create a partial topology. - hr = CreateTopologyFromSource(&topology); - if (FAILED(hr)) - goto done; - } else { - // Creating topology for a transcoder requires a somewhat different setup. - fprintf(stderr, "OpenURL: using archive sink\n"); - hr = MFCreateTranscodeProfile(&transcode_profile_); - if (FAILED(hr)) - goto done; - /* - hr = ConfigureTranscodeAudioOutput(); - if (FAILED(hr)) - goto done; - fprintf(stderr, "OpenURL: Configured audio output\n"); - */ - hr = ConfigureTranscodeVideoOutput(); - if (FAILED(hr)) - goto done; - fprintf(stderr, "OpenURL: Configured video output\n"); - hr = ConfigureContainer(); - if (FAILED(hr)) - goto done; - fprintf(stderr, "OpenURL: Configured container\n"); - hr = MFCreateTranscodeTopology(source_, out_url, transcode_profile_, - &topology); - if (FAILED(hr)) - goto done; - fprintf(stderr, "OpenURL: Created transcode topology\n"); - } - // First argument is flags (which is none). - hr = session_->SetTopology(0, topology); - if (FAILED(hr)) - goto done; - fprintf(stderr, "Added topology to session\n"); - // SetTopology() is an asynchronous method. If it succeeds, the media - // session will queue an MESessionTopologySet event. - // SetTopology() without MFSESSION_SETTOPOLOGY_NORESOLUTION means the - // topology is to be resolved. - state_ = OPEN_PENDING; - done: - if (FAILED(hr)) - state_ = CLOSED; - SafeRelease(&topology); - return SUCCEEDED(hr); -} - -bool MFPlayer::Play() { - if (state_ != PAUSED && state_ != STOPPED) - return false; - if (!session_ || !source_) - return false; - HRESULT hr = StartPlayback(); - return SUCCEEDED(hr); -} - -bool MFPlayer::Pause() { - if (state_ != STARTED) - return false; - if (!session_ || !source_) - return false; - HRESULT hr = session_->Pause(); - if (SUCCEEDED(hr)) - state_ = PAUSED; - return SUCCEEDED(hr); -} - -bool MFPlayer::Shutdown() { - HRESULT hr = CloseSession(); - if (close_event_) { - CloseHandle(close_event_); - close_event_ = NULL; - } - return SUCCEEDED(hr); -} - -// Callback from application upon receiving an WM_APP_PLAYER event. -// This method is used to process media session events on the -// application's main thread. -HRESULT MFPlayer::HandleEvent(UINT_PTR event_ptr) { - IUnknown* unknown_ptr = reinterpret_cast<IUnknown*>(event_ptr); - IMFMediaEvent* event = NULL; - - if (!unknown_ptr) - return E_POINTER; - // Incremented ref count. - HRESULT hr = unknown_ptr->QueryInterface(IID_PPV_ARGS(&event)); - if (FAILED(hr)) - goto done; - MediaEventType event_type; - HRESULT event_status = S_OK; - hr = event->GetType(&event_type); - if (FAILED(hr)) - goto done; - hr = event->GetStatus(&event_status); - if (FAILED(hr)) - goto done; - // Check if the async operation succeeded. - if (FAILED(event_status)) { - hr = event_status; - goto done; - } - - // Handle the event according to its type. - MF_TOPOSTATUS topology_status = MF_TOPOSTATUS_INVALID; - switch (event_type) { - case MESessionTopologySet: - hr = OnTopologyReady(event); - break; - case MEEndOfPresentation: - hr = OnPresentationEnded(event); - break; - // The MENewPresentation event signals the start of a new presentation. - // However, in many cases, you will not receive this event at all. - // It seems like there is no need to handle other events, but if there - // is a need in the future they can be added here. - } - - done: - SafeRelease(&event); - SafeRelease(&unknown_ptr); - return hr; -} - -// Video functionality implementation -// Called by OnPaint() in application, when it receives a WM_PAINT message. -// The EVR (video_display_) must be notified, i.e. repaint. -bool MFPlayer::Repaint() { - if (video_display_) - return SUCCEEDED(video_display_->RepaintVideo()); - else - return true; -} - -// Called when application receives a WM_SIZE message. -bool MFPlayer::ResizeVideo(WORD Width, WORD Height) { - if (video_display_) { - // Fields are: Left (x), Top (y), Right (x), Bottom (y) - RECT DestRect = { 0, 0, Width, Height }; - // First parameter is the "source rectangle" - NULL means show - // the entire portion of the original rectangle. Default is - // {0, 0, 1, 1}. - return SUCCEEDED(video_display_->SetVideoPosition(NULL, &DestRect)); - } else { - return true; - } -} - -// Private methods - -MFPlayer::MFPlayer(HWND video_window, HWND event_window, - bool render_to_window) - : ref_count_(1), - state_(CLOSED), - session_(NULL), - source_(NULL), - video_display_(NULL), - video_window_(video_window), - event_window_(event_window), - close_event_(NULL), - render_to_window_(render_to_window), - transcode_profile_(NULL) { -} - -MFPlayer::~MFPlayer() { - // If false, app did not call Shutdown(). - assert(!session_); - - // When MFPlayer calls IMediaEventGenerator::BeginGetEvent on the - // media session, it causes the media session to hold a reference - // count on the MFPlayer. - // This creates a circular reference count between MFPlayer and the - // media session. Calling Shutdown breaks the circular reference - // count. - // If CreateInstance fails, the application will not call - // Shutdown. To handle that case, call Shutdown in the destructor. - Shutdown(); -} - -// This method only creates the close event. This method is called from -// CreateInstance(). -HRESULT MFPlayer::Initialize() { - if (close_event_) - return MF_E_ALREADY_INITIALIZED; - HRESULT hr = S_OK; - close_event_ = CreateEvent(NULL, // Not inheritable by child process, if any - FALSE, // Auto-reset - FALSE, // Not signaled initially - NULL); // No name - if (!close_event_) - hr = HRESULT_FROM_WIN32(GetLastError()); - return hr; -} - -HRESULT MFPlayer::CreateSession() { - // Close previous section, if any. - HRESULT hr = CloseSession(); - if (FAILED(hr)) - goto done; - - assert(state_ == CLOSED); - - // First argument is optional configurations. (Which is none) - hr = MFCreateMediaSession(NULL, &session_); - if (FAILED(hr)) - goto done; - - state_ = READY; - if (render_to_window_) { - // Start pulling events from the media session. It calls back the object's - // Invoke method when there is a new event available. - hr = session_->BeginGetEvent(this, NULL); - if (FAILED(hr)) - goto done; - } - done: - return hr; -} - -// Closes the media session. Called from either Shutdown() or CreateSession(). -// The IMFMediaSession::Close method is asynchronous, but the CloseSession -// method waits on the MESessionClosed event. The MESessionClosed event is -// guaranteed to be the last event that the media session fires. -HRESULT MFPlayer::CloseSession() { - HRESULT hr = S_OK; - - SafeRelease(&video_display_); - if (session_) { - state_ = CLOSING; - hr = session_->Close(); - if (FAILED(hr)) - goto done; - // Wait 5 seconds for the close operation to complete, i.e. the close event - // to be signaled. close_event_ only exists for playback mode. - if (render_to_window_) - WaitForSingleObject(close_event_, 5000); - // Now there will (or should) be no more events from this session. - } - // Complete shutdown operations. - // Note: Shutdown()s are synchronous. - if (source_) - source_->Shutdown(); - if (session_) - session_->Shutdown(); - SafeRelease(&source_); - SafeRelease(&session_); - SafeRelease(&transcode_profile_); - state_ = CLOSED; - - done: - return hr; -} - -// Starts the session. In the context of playback, it means starting the -// playback. In the context of writing to file, it means starting the encoding -// operation. -HRESULT MFPlayer::StartPlayback() { - assert(session_); - PROPVARIANT var_start; - PropVariantInit(&var_start); - var_start.vt = VT_EMPTY; - HRESULT hr = session_->Start(&GUID_NULL, &var_start); - if (SUCCEEDED(hr)) { - // Start is an asynchronous operation. However, we can treat our state - // as being already started. - state_ = STARTED; - } - PropVariantClear(&var_start); - return hr; -} - -HRESULT MFPlayer::CreateMediaSource(const WCHAR* url) { - MF_OBJECT_TYPE object_type = MF_OBJECT_INVALID; - IMFSourceResolver* resolver = NULL; - IUnknown* source = NULL; - - // Release the old source. - SafeRelease(&source_); - - HRESULT hr = MFCreateSourceResolver(&resolver); - if (FAILED(hr)) - goto done; - - // Use resolver to create media source. - // Synchronous method, use BeginCreateObjectFromUrl for asynchronous. - hr = resolver->CreateObjectFromURL(url, - MF_RESOLUTION_MEDIASOURCE, - NULL, // Not passing in properties. - &object_type, - &source); // Receives created source. - if (FAILED(hr)) - goto done; - - // Get the IMFMediaSource interface from the media source, i.e. initializes - // source_. - // This call increments the ref count of returned interface. - hr = source->QueryInterface(IID_PPV_ARGS(&source_)); - - done: - // Free up resources, if any were acquired. - SafeRelease(&resolver); - SafeRelease(&source); - return hr; -} - -HRESULT MFPlayer::CreateTopologyFromSource(IMFTopology** topology) { - assert(session_); - assert(source_); - - IMFTopology* temp_topology = NULL; - IMFPresentationDescriptor* presentation_desc = NULL; - DWORD num_streams = 0; - - HRESULT hr = MFCreateTopology(&temp_topology); - if (FAILED(hr)) - goto done; - hr = source_->CreatePresentationDescriptor(&presentation_desc); - if (FAILED(hr)) - goto done; - hr = presentation_desc->GetStreamDescriptorCount(&num_streams); - if (FAILED(hr)) - goto done; - // For each stream, create the topology nodes and add them to the topology. - for (DWORD i = 0; i < num_streams; i++) { - hr = AddBranchToPartialTopology(temp_topology, presentation_desc, i); - if (FAILED(hr)) - goto done; - } - *topology = temp_topology; - (*topology)->AddRef(); - - done: - SafeRelease(&temp_topology); - SafeRelease(&presentation_desc); - return hr; -} - -// Creates a topology node with stream of given index and adds the node to the -// topology. -// Add a topology branch for one stream. -// For each stream, this function does the following: -// 1. Creates a source node associated with the stream. -// 2. Creates an output node for the renderer. -// 3. Connects the two nodes. -// The media session will add any decoders that are needed. -HRESULT MFPlayer::AddBranchToPartialTopology( - IMFTopology* topology, IMFPresentationDescriptor* presentation_desc, - DWORD index) { - assert(topology); - - IMFStreamDescriptor* stream_desc = NULL; - IMFMediaTypeHandler* handler = NULL; - GUID major_type_id = GUID_NULL; - IMFTopologyNode* source_node = NULL; - IMFTopologyNode* output_node = NULL; - BOOL stream_selected = FALSE; - - HRESULT hr = presentation_desc->GetStreamDescriptorByIndex(index, - &stream_selected, - &stream_desc); - if (FAILED(hr)) - goto done; - // Create topology branch only if stream is selected. - if (stream_selected) { - hr = stream_desc->GetMediaTypeHandler(&handler); - if (FAILED(hr)) - goto done; - hr = handler->GetMajorType(&major_type_id); - if (FAILED(hr)) - goto done; - if (major_type_id != MFMediaType_Video) - goto done; - hr = CreateSourceStreamNode(presentation_desc, stream_desc, &source_node); - if (FAILED(hr)) - goto done; - hr = CreateOutputNode(stream_desc, &output_node); - if (FAILED(hr)) - goto done; - // Add both nodes to the topology. - hr = topology->AddNode(source_node); - if (FAILED(hr)) - goto done; - hr = topology->AddNode(output_node); - if (FAILED(hr)) - goto done; - // Connect the 0-th output stream of source node to the 0-th input stream of - // the output node. - hr = source_node->ConnectOutput(0, output_node, 0); - } - - done: - SafeRelease(&stream_desc); - SafeRelease(&source_node); - SafeRelease(&output_node); - SafeRelease(&handler); - return hr; -} - -HRESULT MFPlayer::CreateSourceStreamNode( - IMFPresentationDescriptor* presentation_desc, - IMFStreamDescriptor* stream_desc, IMFTopologyNode** node_ptr) { - if (!source_ || !presentation_desc || !stream_desc || !node_ptr) - return E_POINTER; - IMFTopologyNode* temp_node = NULL; - HRESULT hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &temp_node); - if (FAILED(hr)) - goto done; - // Set attribute of top node source to source_. - hr = temp_node->SetUnknown(MF_TOPONODE_SOURCE, source_); - if (FAILED(hr)) - goto done; - // Set attribute of presentation descriptor. - hr = temp_node->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, - presentation_desc); - if (FAILED(hr)) - goto done; - // Set attribute of stream descriptor. - hr = temp_node->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, stream_desc); - if (FAILED(hr)) - goto done; - *node_ptr = temp_node; - (*node_ptr)->AddRef(); - - done: - SafeRelease(&temp_node); - return hr; -} - -// This function does the following: -// 1. Chooses a renderer based on the media type of the stream. -// 2. Creates an IActivate object for the renderer. IActivate objects allow the -// application to defer its creation. -// 3. Creates an output topology node. -// 4. Sets the IActivate pointer on the node. -HRESULT MFPlayer::CreateOutputNode(IMFStreamDescriptor* stream_desc, - IMFTopologyNode** node_ptr) { - IMFTopologyNode* temp_node = NULL; - IMFMediaTypeHandler* handler = NULL; - IMFActivate* renderer_activate = NULL; - GUID major_type_id = GUID_NULL; - - HRESULT hr = stream_desc->GetMediaTypeHandler(&handler); - if (FAILED(hr)) - goto done; - - // Get the type of the stream (video, audio, etc.) - hr = handler->GetMajorType(&major_type_id); - if (FAILED(hr)) - goto done; - - // Is it a video stream, audio stream, etc.? - // Create an IMFActivate object for the renderer, based on the media type - if (major_type_id == MFMediaType_Video) { - assert(video_window_); - hr = MFCreateVideoRendererActivate(video_window_, &renderer_activate); - } else { - hr = E_FAIL; - } - if (FAILED(hr)) - goto done; - - hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &temp_node); - if (FAILED(hr)) - goto done; - - // Associate the activate object with the node. - hr = temp_node->SetObject(renderer_activate); - if (FAILED(hr)) - goto done; - - *node_ptr = temp_node; - (*node_ptr)->AddRef(); - - done: - SafeRelease(&temp_node); - SafeRelease(&handler); - SafeRelease(&renderer_activate); - return hr; -} - -// Handler for MESessionTopologySet. -// This situation means the new topology is ready for playback. After this -// event is received, any calls to IMFGetService will get service interfaces -// from the new topology. -HRESULT MFPlayer::OnTopologyReady(IMFMediaEvent* event) { -////////// - IMFTopology* full_topology = NULL; - HRESULT hr; - hr = ProbeTopology(event, &full_topology); - if (FAILED(hr)) - fprintf(stderr, "Failed to probe topology\n"); - fprintf(stderr, "Probed topology\n"); - - WORD num_nodes_in_topology; - hr = full_topology->GetNodeCount(&num_nodes_in_topology); - if (FAILED(hr)) { - fprintf(stderr, "GetNodeCount failed\n"); - goto release_topology; - } - fprintf(stderr, "There are %d nodes in topology\n", num_nodes_in_topology); - - for (WORD i = 0; i < num_nodes_in_topology; i++) { - IMFTopologyNode* node = NULL; - hr = full_topology->GetNode(i, &node); - if (FAILED(hr)) { - fprintf(stderr, "failed to get node %d\n", i); - } else { - fprintf(stderr, "got node %d\n", i); - } - SafeRelease(&node); - } - - release_topology: - SafeRelease(&full_topology); - if (render_to_window_) { - // Release the old IMFVideoDisplayControl. - SafeRelease(&video_display_); - // Ask for the IMFVideoDisplayControl interface. This interface is - // implemented by the EVR and is exposed by the media session as a service. - // Note: This call is expected to fail if the source does not have video. - MFGetService(session_, MR_VIDEO_RENDER_SERVICE, - IID_PPV_ARGS(&video_display_)); - // Note: Audio, Video acceleration are also services that can be obtained. - } - hr = StartPlayback(); - return hr; -} - -// Handler for MEEndOfPresentation event. -HRESULT MFPlayer::OnPresentationEnded(IMFMediaEvent* event) { - state_ = STOPPED; - return S_OK; -} - -HRESULT MFPlayer::ConfigureTranscodeAudioOutput() { - assert(transcode_profile_); - - HRESULT hr = S_OK; - DWORD num_available_formats; - IMFCollection* available_types = NULL; - IUnknown* unknown_audio_type = NULL; - IMFMediaType* audio_type = NULL; - IMFAttributes* audio_attributes = NULL; - const GUID OUTPUT_AUDIO_SUBTYPE = MFAudioFormat_AAC; - // Get all available types of output formats. - hr = MFTranscodeGetAudioOutputAvailableTypes(OUTPUT_AUDIO_SUBTYPE, - MFT_ENUM_FLAG_ALL, - NULL, - &available_types); - if (SUCCEEDED(hr)) { - hr = available_types->GetElementCount(&num_available_formats); - if (num_available_formats == 0) - hr = E_UNEXPECTED; - } - if (SUCCEEDED(hr)) { - // Just pick the first available format. - hr = available_types->GetElement(0, &unknown_audio_type); - } - if (SUCCEEDED(hr)) - hr = unknown_audio_type->QueryInterface(IID_PPV_ARGS(&audio_type)); - if (SUCCEEDED(hr)) - hr = MFCreateAttributes(&audio_attributes, 0); - if (SUCCEEDED(hr)) - hr = audio_type->CopyAllItems(audio_attributes); - if (SUCCEEDED(hr)) - hr = audio_attributes->SetGUID(MF_MT_SUBTYPE, OUTPUT_AUDIO_SUBTYPE); - - if (SUCCEEDED(hr)) - hr = transcode_profile_->SetAudioAttributes(audio_attributes); - - SafeRelease(&available_types); - SafeRelease(&unknown_audio_type); - SafeRelease(&audio_type); - SafeRelease(&audio_attributes); - return hr; -} - -HRESULT MFPlayer::ConfigureTranscodeVideoOutput() { - assert(transcode_profile_); - - HRESULT hr = S_OK; - IMFAttributes* video_attributes = NULL; - // We set 5 attributes for our video output: - // 1. Output subtype - // 2. Frame rate - // 3. Frame Size - // 4. Aspect ratio - // 5. Bit rate - hr = MFCreateAttributes(&video_attributes, 5); - if (SUCCEEDED(hr)) - hr = video_attributes->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); - if (SUCCEEDED(hr)) - hr = MFSetAttributeRatio(video_attributes, MF_MT_FRAME_RATE, 30, 1); - if (SUCCEEDED(hr)) - hr = MFSetAttributeSize(video_attributes, MF_MT_FRAME_SIZE, 320, 240); - if (SUCCEEDED(hr)) - hr = MFSetAttributeRatio(video_attributes, MF_MT_PIXEL_ASPECT_RATIO, 1, 1); - if (SUCCEEDED(hr)) - hr = video_attributes->SetUINT32(MF_MT_AVG_BITRATE, 300000); - - if (SUCCEEDED(hr)) - hr = transcode_profile_->SetVideoAttributes(video_attributes); - - SafeRelease(&video_attributes); - return hr; -} - -HRESULT MFPlayer::ConfigureContainer() { - assert(transcode_profile_); - - HRESULT hr = S_OK; - IMFAttributes* container_attributes = NULL; - - hr = MFCreateAttributes(&container_attributes, 2); - // Make the container of MP4 type. - if (SUCCEEDED(hr)) - hr = container_attributes->SetGUID(MF_TRANSCODE_CONTAINERTYPE, - MFTranscodeContainerType_MPEG4); - // Use the default setting. Media Foundation will use the stream - // settings set in ConfigureAudioOutput and ConfigureVideoOutput. - if (SUCCEEDED(hr)) - hr = container_attributes->SetUINT32(MF_TRANSCODE_ADJUST_PROFILE, - MF_TRANSCODE_ADJUST_PROFILE_DEFAULT); - - if (SUCCEEDED(hr)) - hr = transcode_profile_->SetContainerAttributes(container_attributes); - - SafeRelease(&container_attributes); - return hr; -} - -// This method will start getting media session events synchronously. -bool MFPlayer::Transcode() { - assert(session_); - - IMFMediaEvent* event = NULL; - MediaEventType event_type = MEUnknown; - HRESULT hr = S_OK; - HRESULT event_status = S_OK; - - while (event_type != MESessionClosed) { - hr = session_->GetEvent(0, &event); - if (FAILED(hr)) - break; - hr = event->GetType(&event_type); - if (FAILED(hr)) - break; - hr = event->GetStatus(&event_status); - if (FAILED(hr)) - break; - if (FAILED(event_status)) { - hr = event_status; - break; - } - switch (event_type) { - case MESessionTopologySet: - hr = OnTopologyReady(event); - break; - case MESessionStarted: - break; - case MESessionEnded: - hr = session_->Close(); - // Finished encoding. - break; - case MESessionClosed: - // Output file has been created - exit on next iteration. - break; - } - if (FAILED(hr)) - break; - SafeRelease(&event); - } - // Release the last MESessionClosed event. - SafeRelease(&event); - return SUCCEEDED(hr); -} - -} // namespace mfplayer diff --git a/media/tools/mfplayer/mfplayer.h b/media/tools/mfplayer/mfplayer.h deleted file mode 100644 index 6daead1..0000000 --- a/media/tools/mfplayer/mfplayer.h +++ /dev/null @@ -1,168 +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. - -#ifndef MEDIA_TOOLS_MFPLAYER_MFPLAYER_H_ -#define MEDIA_TOOLS_MFPLAYER_MFPLAYER_H_ - -#ifdef _WIN32_WINNT -#undef _WIN32_WINNT -#endif -#ifdef WIN32 -#undef WIN32 -#endif -#ifdef WINVER -#undef WINVER -#endif - -#include <evr.h> // Subclass IMFAsyncCallback - -#include <cassert> - -#include "base/basictypes.h" - -#pragma comment(lib, "d3d9.lib") -#pragma comment(lib, "dwmapi.lib") -#pragma comment(lib, "dxva2.lib") -#pragma comment(lib, "mf.lib") -#pragma comment(lib, "mfplat.lib") -#pragma comment(lib, "mfuuid.lib") -#pragma comment(lib, "shlwapi.lib") -#pragma comment(lib, "strmiids.lib") -#pragma comment(lib, "winmm.lib") - -struct IMFAsyncResult; -struct IMFMediaEvent; -struct IMFMediaSession; -struct IMFMediaSource; -struct IMFPresentationDescriptor; -struct IMFStreamDescriptor; -struct IMFTopology; -struct IMFTopologyNode; -struct IMFTranscodeProfile; -struct IMFVideoDisplayControl; - -namespace mfplayer { - -class MFPlayer : public IMFAsyncCallback { - public: - enum PlayerState { - CLOSED = 0, // No session. - READY, // Session was created, ready to open a file. - OPEN_PENDING, // Session is opening a file. - STARTED, // Session is playing a file. - PAUSED, // Session is paused. - STOPPED, // Session is stopped (ready to play). - CLOSING // Application has closed the session, but is waiting for - // MESessionClosed. - }; - - // This is used to represent a type of event posted to the event_window_. - static const UINT WM_APP_PLAYER_EVENT = WM_APP + 1; - - // Use this to construct a MFPlayer instead of constructor. - static bool CreateInstance(HWND video_window, HWND event_window, - bool render_to_window, MFPlayer** player); - - // Override IUnknown. STDMETHODCALLTYPE, which expands to __stdcall, is - // necessary for overriding the parent class's method. - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, void** object_ptr); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - - // Implement IMFAsyncCallback. - HRESULT STDMETHODCALLTYPE GetParameters(DWORD* flags, DWORD* queue) { - // Implementation of this method is optional, assume default behavior. - return E_NOTIMPL; - } - HRESULT STDMETHODCALLTYPE Invoke(IMFAsyncResult* result); - - // Opens the file specified in url and sends a message to start playback, - // once topology has been completed. For archive sinks, out_url is the - // destination at which the encoded file will be saved. - bool OpenURL(const WCHAR* in_url, const WCHAR* out_url); - - // Starts playback. - bool Play(); - - // Pauses playback. - bool Pause(); - - // Shuts down the media player. Called by the destructor. - bool Shutdown(); - - // Handles messages in the message queue. - HRESULT HandleEvent(UINT_PTR event_ptr); - inline PlayerState state() const { return state_; } - - // Video functionality - bool Repaint(); - bool ResizeVideo(WORD width, WORD height); - inline bool HasVideo() const { return (video_display_ != NULL); } - - // The following methods are used for archive sink. - // Begins the encoding operation. Call this after OpenURL() only. - bool Transcode(); - - private: - // Private constructor: Call CreateInstance() instead. - MFPlayer(HWND video_window, HWND event_window, - bool render_to_window); - - // Caller should use Release() instead, which keeps track of ref count. - ~MFPlayer(); - - // Initializes the media player. This actually only creates an Event object - // to signal closing the media player. - HRESULT Initialize(); - - // Creates the media session object of the player, and starts pulling events - // from it. - HRESULT CreateSession(); - - // The meat of Shutdown(). Releases the source and the session. - HRESULT CloseSession(); - HRESULT StartPlayback(); - HRESULT CreateMediaSource(const WCHAR* url); - - // Creates the partial topology of the player. - HRESULT CreateTopologyFromSource(IMFTopology** topology); - - // Called by CreateTopologyFromSource() to add nodes to the topology, if the - // stream is either video or audio stream. - HRESULT AddBranchToPartialTopology( - IMFTopology* topology, - IMFPresentationDescriptor* presentation_desc, - DWORD index); - HRESULT CreateSourceStreamNode(IMFPresentationDescriptor* presentation_desc, - IMFStreamDescriptor* stream_desc, - IMFTopologyNode** node_ptr); - HRESULT CreateOutputNode(IMFStreamDescriptor* stream_desc, - IMFTopologyNode** node_ptr); - - // Media event handlers - HRESULT OnTopologyReady(IMFMediaEvent* event); - HRESULT OnPresentationEnded(IMFMediaEvent* event); - - // These methods are used for archive sink. - HRESULT ConfigureTranscodeAudioOutput(); - HRESULT ConfigureTranscodeVideoOutput(); - HRESULT ConfigureContainer(); - - LONG ref_count_; - PlayerState state_; - IMFMediaSession* session_; - IMFMediaSource* source_; - IMFVideoDisplayControl* video_display_; - HWND video_window_; - HWND event_window_; - HANDLE close_event_; - bool render_to_window_; - IMFTranscodeProfile* transcode_profile_; - - DISALLOW_COPY_AND_ASSIGN(MFPlayer); -}; - -} // namespace mfplayer - -#endif // MEDIA_TOOLS_MFPLAYER_MFPLAYER_H_ |