Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1583)

Side by Side Diff: media/base/media_win.cc

Issue 9450001: Workaround for Windows-only crash inside delay load helper. (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/base/media.h" 5 #include "media/base/media.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <delayimp.h>
9
10 #include <string>
8 11
9 #include "base/file_path.h" 12 #include "base/file_path.h"
10 #include "base/logging.h" 13 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_ptr.h"
12 #include "base/native_library.h" 15 #include "base/native_library.h"
13 #include "base/path_service.h" 16 #include "base/path_service.h"
14 17
18 #pragma comment(lib, "delayimp.lib")
19
15 namespace media { 20 namespace media {
16 21
17 enum FFmpegDLLKeys { 22 enum FFmpegDLLKeys {
18 FILE_LIBAVCODEC, // full path to libavcodec media decoding library. 23 FILE_LIBAVCODEC, // full path to libavcodec media decoding library.
19 FILE_LIBAVFORMAT, // full path to libavformat media parsing library. 24 FILE_LIBAVFORMAT, // full path to libavformat media parsing library.
20 FILE_LIBAVUTIL, // full path to libavutil media utility library. 25 FILE_LIBAVUTIL, // full path to libavutil media utility library.
21 }; 26 };
22 27
23 // Retrieves the DLLName for the given key. 28 // Retrieves the DLLName for the given key.
24 static FilePath::CharType* GetDLLName(FFmpegDLLKeys dll_key) { 29 static const char* GetDLLName(FFmpegDLLKeys dll_key) {
25 // TODO(ajwong): Do we want to lock to a specific ffmpeg version? 30 // TODO(ajwong): Do we want to lock to a specific ffmpeg version?
26 switch (dll_key) { 31 switch (dll_key) {
27 case FILE_LIBAVCODEC: 32 case FILE_LIBAVCODEC:
28 return FILE_PATH_LITERAL("avcodec-53.dll"); 33 return "avcodec-53.dll";
scherkus (not reviewing) 2012/02/23 05:22:55 dalecurtis: do these need updated?
DaleCurtis 2012/02/23 21:03:08 Not since the FFmpeg roll got reverted. Just make
29 case FILE_LIBAVFORMAT: 34 case FILE_LIBAVFORMAT:
30 return FILE_PATH_LITERAL("avformat-53.dll"); 35 return "avformat-53.dll";
31 case FILE_LIBAVUTIL: 36 case FILE_LIBAVUTIL:
32 return FILE_PATH_LITERAL("avutil-51.dll"); 37 return "avutil-51.dll";
33 default: 38 default:
34 LOG(DFATAL) << "Invalid DLL key requested: " << dll_key; 39 LOG(DFATAL) << "Invalid DLL key requested: " << dll_key;
35 return FILE_PATH_LITERAL(""); 40 return "";
36 } 41 }
37 } 42 }
38 43
39 static bool g_media_library_is_initialized = false; 44 static bool g_media_library_is_initialized = false;
40 45
46 // Handler for SEH when delay loading -- we want to catch everything
47 // delayload-related, but crash on access violation and such.
48 static int delay_load_exception_filter(unsigned int exception_code) {
49 switch (exception_code) {
50 case VcppException(ERROR_SEVERITY_ERROR, ERROR_INVALID_PARAMETER):
51 case VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND):
52 case VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND):
53 return EXCEPTION_EXECUTE_HANDLER;
cpu_(ooo_6.6-7.5) 2012/02/23 23:58:25 I don't understand the purpose of the patch. You s
54 default:
55 return EXCEPTION_CONTINUE_SEARCH;
56 }
57 }
58
59 // Fixes import table for DLL. Returns true if succeed, false otherwise.
scherkus (not reviewing) 2012/02/23 05:22:55 so this function doesn't require absolute paths?
60 static bool PatchImportTable(const char *dll) {
scherkus (not reviewing) 2012/02/23 05:22:55 pointer w/ type: const char* dll
61 __try {
62 if (FAILED(::__HrLoadAllImportsForDll(dll)))
63 return false;
64 } __except(delay_load_exception_filter(GetExceptionCode())) {
65 return false;
66 }
67 return true;
68 }
69
41 // Attempts to initialize the media library (loading DLLs, DSOs, etc.). 70 // Attempts to initialize the media library (loading DLLs, DSOs, etc.).
42 // Returns true if everything was successfully initialized, false otherwise. 71 // Returns true if everything was successfully initialized, false otherwise.
43 bool InitializeMediaLibrary(const FilePath& base_path) { 72 bool InitializeMediaLibrary(const FilePath& base_path) {
44 if (g_media_library_is_initialized) 73 if (g_media_library_is_initialized)
45 return true; 74 return true;
46 75
47 FFmpegDLLKeys path_keys[] = { 76 FFmpegDLLKeys path_keys[] = {
48 media::FILE_LIBAVCODEC, 77 media::FILE_LIBAVCODEC,
49 media::FILE_LIBAVFORMAT, 78 media::FILE_LIBAVFORMAT,
50 media::FILE_LIBAVUTIL 79 media::FILE_LIBAVUTIL
51 }; 80 };
52 HMODULE libs[arraysize(path_keys)] = {NULL}; 81 HMODULE libs[arraysize(path_keys)] = {NULL};
53 82
83 // Convert to absolute path, customer can specify relative path by
84 // command-line flag, and LoadLibraryEx(..., LOAD_WITH_ALTERED_SEARCH_PATH)
85 // does not allow relative paths.
86 DWORD full_path_len = ::GetFullPathName(base_path.value().c_str(),
scherkus (not reviewing) 2012/02/23 05:22:55 perhaps turn this into a function like GetFullFile
87 0,
88 NULL,
89 NULL);
90 if (full_path_len == 0)
91 return false;
92 std::wstring full_path(full_path_len, 0);
93 ::GetFullPathName(base_path.value().c_str(),
94 full_path_len,
95 &full_path[0],
96 NULL);
97 full_path.resize(full_path_len - 1); // Get rid of terminating NUL character.
98
54 for (size_t i = 0; i < arraysize(path_keys); ++i) { 99 for (size_t i = 0; i < arraysize(path_keys); ++i) {
55 FilePath path = base_path.Append(GetDLLName(path_keys[i])); 100 FilePath path(full_path);
101 path = path.AppendASCII(GetDLLName(path_keys[i]));
56 102
57 // Use alternate DLL search path so we don't load dependencies from the 103 // Use alternate DLL search path so we don't load dependencies from the
58 // system path. Refer to http://crbug.com/35857 104 // system path. Refer to http://crbug.com/35857
59 const wchar_t* cpath = path.value().c_str(); 105 const wchar_t* cpath = path.value().c_str();
60 libs[i] = LoadLibraryEx(cpath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); 106 libs[i] = ::LoadLibraryEx(cpath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
61 if (!libs[i]) 107 if (!libs[i])
62 break; 108 break;
63 } 109 }
64 110
65 // Check that we loaded all libraries successfully. We only need to check the 111 // Check that we loaded all libraries successfully. We only need to check the
66 // last array element because the loop above will break without initializing 112 // last array element because the loop above will break without initializing
67 // it on any prior error. 113 // it on any prior error.
68 g_media_library_is_initialized = (libs[arraysize(libs) - 1] != NULL); 114 bool media_library_is_initialized = (libs[arraysize(libs) - 1] != NULL);
69 115
70 if (!g_media_library_is_initialized) { 116 if (!media_library_is_initialized) {
71 // Free any loaded libraries if we weren't successful. 117 // Free any loaded libraries if we weren't successful.
72 for (size_t i = 0; i < arraysize(libs) && libs[i] != NULL; ++i) { 118 for (size_t i = 0; i < arraysize(libs) && libs[i] != NULL; ++i) {
73 FreeLibrary(libs[i]); 119 FreeLibrary(libs[i]);
74 libs[i] = NULL; // Just to be safe. 120 libs[i] = NULL; // Just to be safe.
75 } 121 }
122 return false;
76 } 123 }
77 124
78 return g_media_library_is_initialized; 125 // Workaround for http://crbug.com/110983
126 // LoadLibrary() sometimes AV's when called by delay load helper when we
scherkus (not reviewing) 2012/02/23 05:22:55 what's AV?
127 // call function in ffmpeg for the first time, and we don't know why.
128 // Force delay load helper to fix import table here instead.
129 // Theoretically, there is no need to call LoadLibrary() before
130 // __HrLoadAllImportsForDll(), it will call LoadLibrary() itself, but there
131 // is no way to specify LOAD_WITH_ALTERED_SEARCH_PATH when calling
132 // __HrLoadAllImportsForDll(). So we do everything in 2 steps -- first call
133 // LoadLibraryEx(..., LOAD_WITH_ALTERED_SEARCH_PATH), then call
134 // __HrLoadAllImportsForDll(). Overhead is negligible compared to disk
135 // access time.
136 // Note: in case of error we are not unloading DLL because unload requires
137 // extra resources and should not be necessary; if we ever decide to
138 // unload by calling __FUnloadDelayLoadedDLL() please add /DELAY:UNLOAD
139 // to the linker command line.
140 for (size_t i = 0; i < arraysize(path_keys); ++i) {
141 media_library_is_initialized &= PatchImportTable(GetDLLName(path_keys[i]));
142 }
143
144 g_media_library_is_initialized = media_library_is_initialized;
145 return media_library_is_initialized;
79 } 146 }
80 147
81 void InitializeMediaLibraryForTesting() { 148 void InitializeMediaLibraryForTesting() {
82 FilePath file_path; 149 FilePath file_path;
83 CHECK(PathService::Get(base::DIR_EXE, &file_path)); 150 CHECK(PathService::Get(base::DIR_EXE, &file_path));
84 CHECK(InitializeMediaLibrary(file_path)); 151 CHECK(InitializeMediaLibrary(file_path));
85 } 152 }
86 153
87 bool IsMediaLibraryInitialized() { 154 bool IsMediaLibraryInitialized() {
88 return g_media_library_is_initialized; 155 return g_media_library_is_initialized;
89 } 156 }
90 157
91 bool InitializeOpenMaxLibrary(const FilePath& module_dir) { 158 bool InitializeOpenMaxLibrary(const FilePath& module_dir) {
92 NOTIMPLEMENTED() << "OpenMAX is not used in Windows."; 159 NOTIMPLEMENTED() << "OpenMAX is not used in Windows.";
93 return false; 160 return false;
94 } 161 }
95 162
96 } // namespace media 163 } // namespace media
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698