diff options
author | Jacek Antonelli | 2008-08-15 23:45:04 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:45:04 -0500 |
commit | 117e22047c5752352342d64e3fb7ce00a4eb8113 (patch) | |
tree | e32de2cfba0dda8705ae528fcd1fbe23ba075685 /linden/indra/llmedia | |
parent | Second Life viewer sources 1.18.0.6 (diff) | |
download | meta-impy-117e22047c5752352342d64e3fb7ce00a4eb8113.zip meta-impy-117e22047c5752352342d64e3fb7ce00a4eb8113.tar.gz meta-impy-117e22047c5752352342d64e3fb7ce00a4eb8113.tar.bz2 meta-impy-117e22047c5752352342d64e3fb7ce00a4eb8113.tar.xz |
Second Life viewer sources 1.18.1.2
Diffstat (limited to 'linden/indra/llmedia')
-rw-r--r-- | linden/indra/llmedia/files.lst | 3 | ||||
-rw-r--r-- | linden/indra/llmedia/llmedia_vc8.vcproj | 594 | ||||
-rw-r--r-- | linden/indra/llmedia/llmediabase.cpp | 8 | ||||
-rw-r--r-- | linden/indra/llmedia/llmediaimplgstreamer.cpp | 715 | ||||
-rw-r--r-- | linden/indra/llmedia/llmediaimplgstreamer.h | 126 | ||||
-rw-r--r-- | linden/indra/llmedia/llmediaimplgstreamer_syms.cpp | 189 | ||||
-rw-r--r-- | linden/indra/llmedia/llmediaimplgstreamer_syms.h | 75 | ||||
-rw-r--r-- | linden/indra/llmedia/llmediaimplgstreamer_syms_raw.inc | 42 | ||||
-rw-r--r-- | linden/indra/llmedia/llmediaimplgstreamer_syms_rawa.inc | 5 | ||||
-rw-r--r-- | linden/indra/llmedia/llmediaimplgstreamer_syms_rawv.inc | 5 | ||||
-rw-r--r-- | linden/indra/llmedia/llmediaimplgstreamervidplug.cpp | 461 | ||||
-rw-r--r-- | linden/indra/llmedia/llmediaimplgstreamervidplug.h | 101 | ||||
-rw-r--r-- | linden/indra/llmedia/llmediamoviebase.cpp | 8 |
13 files changed, 2035 insertions, 297 deletions
diff --git a/linden/indra/llmedia/files.lst b/linden/indra/llmedia/files.lst index 35ae5ab..bda6459 100644 --- a/linden/indra/llmedia/files.lst +++ b/linden/indra/llmedia/files.lst | |||
@@ -1,4 +1,7 @@ | |||
1 | llmedia/llmediabase.cpp | 1 | llmedia/llmediabase.cpp |
2 | llmedia/llmediaengine.cpp | 2 | llmedia/llmediaengine.cpp |
3 | llmedia/llmediaimplgstreamer.cpp | ||
4 | llmedia/llmediaimplgstreamer_syms.cpp | ||
5 | llmedia/llmediaimplgstreamervidplug.cpp | ||
3 | llmedia/llmediaimplquicktime.cpp | 6 | llmedia/llmediaimplquicktime.cpp |
4 | llmedia/llmediamoviebase.cpp | 7 | llmedia/llmediamoviebase.cpp |
diff --git a/linden/indra/llmedia/llmedia_vc8.vcproj b/linden/indra/llmedia/llmedia_vc8.vcproj index 12fa817..2bc8014 100644 --- a/linden/indra/llmedia/llmedia_vc8.vcproj +++ b/linden/indra/llmedia/llmedia_vc8.vcproj | |||
@@ -1,297 +1,297 @@ | |||
1 | <?xml version="1.0" encoding="Windows-1252"?> | 1 | <?xml version="1.0" encoding="Windows-1252"?> |
2 | <VisualStudioProject | 2 | <VisualStudioProject |
3 | ProjectType="Visual C++" | 3 | ProjectType="Visual C++" |
4 | Version="8.00" | 4 | Version="8.00" |
5 | Name="llmedia" | 5 | Name="llmedia" |
6 | ProjectGUID="{9D0C7E02-6506-4EE7-BC5C-75671D28D594}" | 6 | ProjectGUID="{9D0C7E02-6506-4EE7-BC5C-75671D28D594}" |
7 | RootNamespace="llmedia" | 7 | RootNamespace="llmedia" |
8 | Keyword="Win32Proj" | 8 | Keyword="Win32Proj" |
9 | > | 9 | > |
10 | <Platforms> | 10 | <Platforms> |
11 | <Platform | 11 | <Platform |
12 | Name="Win32" | 12 | Name="Win32" |
13 | /> | 13 | /> |
14 | </Platforms> | 14 | </Platforms> |
15 | <ToolFiles> | 15 | <ToolFiles> |
16 | </ToolFiles> | 16 | </ToolFiles> |
17 | <Configurations> | 17 | <Configurations> |
18 | <Configuration | 18 | <Configuration |
19 | Name="Debug|Win32" | 19 | Name="Debug|Win32" |
20 | OutputDirectory="../lib_$(ConfigurationName)/i686-win32" | 20 | OutputDirectory="../lib_$(ConfigurationName)/i686-win32" |
21 | IntermediateDirectory="Debug" | 21 | IntermediateDirectory="Debug" |
22 | ConfigurationType="4" | 22 | ConfigurationType="4" |
23 | InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" | 23 | InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" |
24 | CharacterSet="1" | 24 | CharacterSet="1" |
25 | > | 25 | > |
26 | <Tool | 26 | <Tool |
27 | Name="VCPreBuildEventTool" | 27 | Name="VCPreBuildEventTool" |
28 | /> | 28 | /> |
29 | <Tool | 29 | <Tool |
30 | Name="VCCustomBuildTool" | 30 | Name="VCCustomBuildTool" |
31 | /> | 31 | /> |
32 | <Tool | 32 | <Tool |
33 | Name="VCXMLDataGeneratorTool" | 33 | Name="VCXMLDataGeneratorTool" |
34 | /> | 34 | /> |
35 | <Tool | 35 | <Tool |
36 | Name="VCWebServiceProxyGeneratorTool" | 36 | Name="VCWebServiceProxyGeneratorTool" |
37 | /> | 37 | /> |
38 | <Tool | 38 | <Tool |
39 | Name="VCMIDLTool" | 39 | Name="VCMIDLTool" |
40 | /> | 40 | /> |
41 | <Tool | 41 | <Tool |
42 | Name="VCCLCompilerTool" | 42 | Name="VCCLCompilerTool" |
43 | Optimization="0" | 43 | Optimization="0" |
44 | AdditionalIncludeDirectories="..\llcommon;..\llrender;..\llwindow;..\llimage;..\llmath;..\llvfs;..\llmessage;..\llui;"..\..\libraries\i686-win32\include";..\..\libraries\include\;"..\..\libraries\i686-win32\include\quicktime"" | 44 | AdditionalIncludeDirectories="..\llcommon;..\llrender;..\llwindow;..\llimage;..\llmath;..\llvfs;..\llmessage;..\llui;"..\..\libraries\i686-win32\include";..\..\libraries\include\;"..\..\libraries\i686-win32\include\quicktime"" |
45 | PreprocessorDefinitions="WIN32;_DEBUG;_LIB;LL_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;LL_DEBUG;XP_WIN;XP_WIN32" | 45 | PreprocessorDefinitions="WIN32;_DEBUG;_LIB;LL_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;LL_DEBUG;XP_WIN;XP_WIN32" |
46 | MinimalRebuild="true" | 46 | MinimalRebuild="true" |
47 | BasicRuntimeChecks="3" | 47 | BasicRuntimeChecks="3" |
48 | RuntimeLibrary="1" | 48 | RuntimeLibrary="1" |
49 | StructMemberAlignment="4" | 49 | StructMemberAlignment="4" |
50 | TreatWChar_tAsBuiltInType="false" | 50 | TreatWChar_tAsBuiltInType="false" |
51 | ForceConformanceInForLoopScope="true" | 51 | ForceConformanceInForLoopScope="true" |
52 | UsePrecompiledHeader="0" | 52 | UsePrecompiledHeader="0" |
53 | WarningLevel="3" | 53 | WarningLevel="3" |
54 | WarnAsError="true" | 54 | WarnAsError="true" |
55 | Detect64BitPortabilityProblems="false" | 55 | Detect64BitPortabilityProblems="false" |
56 | DebugInformationFormat="4" | 56 | DebugInformationFormat="4" |
57 | DisableSpecificWarnings="4702" | 57 | DisableSpecificWarnings="4702" |
58 | /> | 58 | /> |
59 | <Tool | 59 | <Tool |
60 | Name="VCManagedResourceCompilerTool" | 60 | Name="VCManagedResourceCompilerTool" |
61 | /> | 61 | /> |
62 | <Tool | 62 | <Tool |
63 | Name="VCResourceCompilerTool" | 63 | Name="VCResourceCompilerTool" |
64 | /> | 64 | /> |
65 | <Tool | 65 | <Tool |
66 | Name="VCPreLinkEventTool" | 66 | Name="VCPreLinkEventTool" |
67 | /> | 67 | /> |
68 | <Tool | 68 | <Tool |
69 | Name="VCLibrarianTool" | 69 | Name="VCLibrarianTool" |
70 | OutputFile="$(OutDir)/llmedia.lib" | 70 | OutputFile="$(OutDir)/llmedia.lib" |
71 | AdditionalLibraryDirectories="" | 71 | AdditionalLibraryDirectories="" |
72 | /> | 72 | /> |
73 | <Tool | 73 | <Tool |
74 | Name="VCALinkTool" | 74 | Name="VCALinkTool" |
75 | /> | 75 | /> |
76 | <Tool | 76 | <Tool |
77 | Name="VCXDCMakeTool" | 77 | Name="VCXDCMakeTool" |
78 | /> | 78 | /> |
79 | <Tool | 79 | <Tool |
80 | Name="VCBscMakeTool" | 80 | Name="VCBscMakeTool" |
81 | /> | 81 | /> |
82 | <Tool | 82 | <Tool |
83 | Name="VCFxCopTool" | 83 | Name="VCFxCopTool" |
84 | /> | 84 | /> |
85 | <Tool | 85 | <Tool |
86 | Name="VCPostBuildEventTool" | 86 | Name="VCPostBuildEventTool" |
87 | /> | 87 | /> |
88 | </Configuration> | 88 | </Configuration> |
89 | <Configuration | 89 | <Configuration |
90 | Name="Release|Win32" | 90 | Name="Release|Win32" |
91 | OutputDirectory="../lib_$(ConfigurationName)/i686-win32" | 91 | OutputDirectory="../lib_$(ConfigurationName)/i686-win32" |
92 | IntermediateDirectory="Release" | 92 | IntermediateDirectory="Release" |
93 | ConfigurationType="4" | 93 | ConfigurationType="4" |
94 | InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" | 94 | InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" |
95 | CharacterSet="1" | 95 | CharacterSet="1" |
96 | > | 96 | > |
97 | <Tool | 97 | <Tool |
98 | Name="VCPreBuildEventTool" | 98 | Name="VCPreBuildEventTool" |
99 | /> | 99 | /> |
100 | <Tool | 100 | <Tool |
101 | Name="VCCustomBuildTool" | 101 | Name="VCCustomBuildTool" |
102 | /> | 102 | /> |
103 | <Tool | 103 | <Tool |
104 | Name="VCXMLDataGeneratorTool" | 104 | Name="VCXMLDataGeneratorTool" |
105 | /> | 105 | /> |
106 | <Tool | 106 | <Tool |
107 | Name="VCWebServiceProxyGeneratorTool" | 107 | Name="VCWebServiceProxyGeneratorTool" |
108 | /> | 108 | /> |
109 | <Tool | 109 | <Tool |
110 | Name="VCMIDLTool" | 110 | Name="VCMIDLTool" |
111 | /> | 111 | /> |
112 | <Tool | 112 | <Tool |
113 | Name="VCCLCompilerTool" | 113 | Name="VCCLCompilerTool" |
114 | InlineFunctionExpansion="0" | 114 | InlineFunctionExpansion="0" |
115 | EnableIntrinsicFunctions="false" | 115 | EnableIntrinsicFunctions="false" |
116 | AdditionalIncludeDirectories="..\llcommon;..\llrender;..\llwindow;..\llimage;..\llmath;..\llvfs;..\llmessage;..\llui;"..\..\libraries\i686-win32\include";..\..\libraries\include\;"..\..\libraries\i686-win32\include\quicktime"" | 116 | AdditionalIncludeDirectories="..\llcommon;..\llrender;..\llwindow;..\llimage;..\llmath;..\llvfs;..\llmessage;..\llui;"..\..\libraries\i686-win32\include";..\..\libraries\include\;"..\..\libraries\i686-win32\include\quicktime"" |
117 | PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;LL_RELEASE;XP_WIN;XP_WIN32" | 117 | PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;LL_RELEASE;XP_WIN;XP_WIN32" |
118 | RuntimeLibrary="0" | 118 | RuntimeLibrary="0" |
119 | StructMemberAlignment="0" | 119 | StructMemberAlignment="0" |
120 | TreatWChar_tAsBuiltInType="false" | 120 | TreatWChar_tAsBuiltInType="false" |
121 | ForceConformanceInForLoopScope="true" | 121 | ForceConformanceInForLoopScope="true" |
122 | UsePrecompiledHeader="0" | 122 | UsePrecompiledHeader="0" |
123 | WarningLevel="3" | 123 | WarningLevel="3" |
124 | WarnAsError="false" | 124 | WarnAsError="false" |
125 | Detect64BitPortabilityProblems="false" | 125 | Detect64BitPortabilityProblems="false" |
126 | DebugInformationFormat="3" | 126 | DebugInformationFormat="3" |
127 | DisableSpecificWarnings="4702" | 127 | DisableSpecificWarnings="4702" |
128 | /> | 128 | /> |
129 | <Tool | 129 | <Tool |
130 | Name="VCManagedResourceCompilerTool" | 130 | Name="VCManagedResourceCompilerTool" |
131 | /> | 131 | /> |
132 | <Tool | 132 | <Tool |
133 | Name="VCResourceCompilerTool" | 133 | Name="VCResourceCompilerTool" |
134 | /> | 134 | /> |
135 | <Tool | 135 | <Tool |
136 | Name="VCPreLinkEventTool" | 136 | Name="VCPreLinkEventTool" |
137 | /> | 137 | /> |
138 | <Tool | 138 | <Tool |
139 | Name="VCLibrarianTool" | 139 | Name="VCLibrarianTool" |
140 | OutputFile="$(OutDir)/llmedia.lib" | 140 | OutputFile="$(OutDir)/llmedia.lib" |
141 | AdditionalLibraryDirectories="" | 141 | AdditionalLibraryDirectories="" |
142 | IgnoreAllDefaultLibraries="false" | 142 | IgnoreAllDefaultLibraries="false" |
143 | IgnoreDefaultLibraryNames="" | 143 | IgnoreDefaultLibraryNames="" |
144 | /> | 144 | /> |
145 | <Tool | 145 | <Tool |
146 | Name="VCALinkTool" | 146 | Name="VCALinkTool" |
147 | /> | 147 | /> |
148 | <Tool | 148 | <Tool |
149 | Name="VCXDCMakeTool" | 149 | Name="VCXDCMakeTool" |
150 | /> | 150 | /> |
151 | <Tool | 151 | <Tool |
152 | Name="VCBscMakeTool" | 152 | Name="VCBscMakeTool" |
153 | /> | 153 | /> |
154 | <Tool | 154 | <Tool |
155 | Name="VCFxCopTool" | 155 | Name="VCFxCopTool" |
156 | /> | 156 | /> |
157 | <Tool | 157 | <Tool |
158 | Name="VCPostBuildEventTool" | 158 | Name="VCPostBuildEventTool" |
159 | /> | 159 | /> |
160 | </Configuration> | 160 | </Configuration> |
161 | <Configuration | 161 | <Configuration |
162 | Name="ReleaseNoOpt|Win32" | 162 | Name="ReleaseNoOpt|Win32" |
163 | OutputDirectory="../lib_$(ConfigurationName)/i686-win32" | 163 | OutputDirectory="../lib_$(ConfigurationName)/i686-win32" |
164 | IntermediateDirectory="$(ConfigurationName)" | 164 | IntermediateDirectory="$(ConfigurationName)" |
165 | ConfigurationType="4" | 165 | ConfigurationType="4" |
166 | InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" | 166 | InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" |
167 | CharacterSet="1" | 167 | CharacterSet="1" |
168 | > | 168 | > |
169 | <Tool | 169 | <Tool |
170 | Name="VCPreBuildEventTool" | 170 | Name="VCPreBuildEventTool" |
171 | /> | 171 | /> |
172 | <Tool | 172 | <Tool |
173 | Name="VCCustomBuildTool" | 173 | Name="VCCustomBuildTool" |
174 | /> | 174 | /> |
175 | <Tool | 175 | <Tool |
176 | Name="VCXMLDataGeneratorTool" | 176 | Name="VCXMLDataGeneratorTool" |
177 | /> | 177 | /> |
178 | <Tool | 178 | <Tool |
179 | Name="VCWebServiceProxyGeneratorTool" | 179 | Name="VCWebServiceProxyGeneratorTool" |
180 | /> | 180 | /> |
181 | <Tool | 181 | <Tool |
182 | Name="VCMIDLTool" | 182 | Name="VCMIDLTool" |
183 | /> | 183 | /> |
184 | <Tool | 184 | <Tool |
185 | Name="VCCLCompilerTool" | 185 | Name="VCCLCompilerTool" |
186 | Optimization="0" | 186 | Optimization="0" |
187 | InlineFunctionExpansion="0" | 187 | InlineFunctionExpansion="0" |
188 | EnableIntrinsicFunctions="false" | 188 | EnableIntrinsicFunctions="false" |
189 | AdditionalIncludeDirectories="..\llcommon;..\llrender;..\llwindow;..\llimage;..\llmath;..\llvfs;..\llmessage;..\llui;"..\..\libraries\i686-win32\include";..\..\libraries\include\;"..\..\libraries\i686-win32\include\quicktime"" | 189 | AdditionalIncludeDirectories="..\llcommon;..\llrender;..\llwindow;..\llimage;..\llmath;..\llvfs;..\llmessage;..\llui;"..\..\libraries\i686-win32\include";..\..\libraries\include\;"..\..\libraries\i686-win32\include\quicktime"" |
190 | PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;LL_RELEASE;XP_WIN;XP_WIN32" | 190 | PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;LL_RELEASE;XP_WIN;XP_WIN32" |
191 | RuntimeLibrary="0" | 191 | RuntimeLibrary="0" |
192 | StructMemberAlignment="0" | 192 | StructMemberAlignment="0" |
193 | TreatWChar_tAsBuiltInType="false" | 193 | TreatWChar_tAsBuiltInType="false" |
194 | ForceConformanceInForLoopScope="true" | 194 | ForceConformanceInForLoopScope="true" |
195 | UsePrecompiledHeader="0" | 195 | UsePrecompiledHeader="0" |
196 | WarningLevel="3" | 196 | WarningLevel="3" |
197 | WarnAsError="true" | 197 | WarnAsError="true" |
198 | Detect64BitPortabilityProblems="false" | 198 | Detect64BitPortabilityProblems="false" |
199 | DebugInformationFormat="3" | 199 | DebugInformationFormat="3" |
200 | DisableSpecificWarnings="4702" | 200 | DisableSpecificWarnings="4702" |
201 | /> | 201 | /> |
202 | <Tool | 202 | <Tool |
203 | Name="VCManagedResourceCompilerTool" | 203 | Name="VCManagedResourceCompilerTool" |
204 | /> | 204 | /> |
205 | <Tool | 205 | <Tool |
206 | Name="VCResourceCompilerTool" | 206 | Name="VCResourceCompilerTool" |
207 | /> | 207 | /> |
208 | <Tool | 208 | <Tool |
209 | Name="VCPreLinkEventTool" | 209 | Name="VCPreLinkEventTool" |
210 | /> | 210 | /> |
211 | <Tool | 211 | <Tool |
212 | Name="VCLibrarianTool" | 212 | Name="VCLibrarianTool" |
213 | OutputFile="$(OutDir)/llmedia.lib" | 213 | OutputFile="$(OutDir)/llmedia.lib" |
214 | AdditionalLibraryDirectories="" | 214 | AdditionalLibraryDirectories="" |
215 | IgnoreAllDefaultLibraries="false" | 215 | IgnoreAllDefaultLibraries="false" |
216 | IgnoreDefaultLibraryNames="" | 216 | IgnoreDefaultLibraryNames="" |
217 | /> | 217 | /> |
218 | <Tool | 218 | <Tool |
219 | Name="VCALinkTool" | 219 | Name="VCALinkTool" |
220 | /> | 220 | /> |
221 | <Tool | 221 | <Tool |
222 | Name="VCXDCMakeTool" | 222 | Name="VCXDCMakeTool" |
223 | /> | 223 | /> |
224 | <Tool | 224 | <Tool |
225 | Name="VCBscMakeTool" | 225 | Name="VCBscMakeTool" |
226 | /> | 226 | /> |
227 | <Tool | 227 | <Tool |
228 | Name="VCFxCopTool" | 228 | Name="VCFxCopTool" |
229 | /> | 229 | /> |
230 | <Tool | 230 | <Tool |
231 | Name="VCPostBuildEventTool" | 231 | Name="VCPostBuildEventTool" |
232 | /> | 232 | /> |
233 | </Configuration> | 233 | </Configuration> |
234 | </Configurations> | 234 | </Configurations> |
235 | <References> | 235 | <References> |
236 | </References> | 236 | </References> |
237 | <Files> | 237 | <Files> |
238 | <Filter | 238 | <Filter |
239 | Name="Source Files" | 239 | Name="Source Files" |
240 | Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" | 240 | Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" |
241 | UniqueIdentifier="{44DBC47A-0AF0-4726-A094-2D6FBB65FFFA}" | 241 | UniqueIdentifier="{44DBC47A-0AF0-4726-A094-2D6FBB65FFFA}" |
242 | > | 242 | > |
243 | <File | 243 | <File |
244 | RelativePath=".\llmediabase.cpp" | 244 | RelativePath=".\llmediabase.cpp" |
245 | > | 245 | > |
246 | </File> | 246 | </File> |
247 | <File | 247 | <File |
248 | RelativePath=".\llmediaengine.cpp" | 248 | RelativePath=".\llmediaengine.cpp" |
249 | > | 249 | > |
250 | </File> | 250 | </File> |
251 | <File | 251 | <File |
252 | RelativePath=".\llmediaimplquicktime.cpp" | 252 | RelativePath=".\llmediaimplquicktime.cpp" |
253 | > | 253 | > |
254 | </File> | 254 | </File> |
255 | <File | 255 | <File |
256 | RelativePath=".\llmediamoviebase.cpp" | 256 | RelativePath=".\llmediamoviebase.cpp" |
257 | > | 257 | > |
258 | </File> | 258 | </File> |
259 | <File | 259 | <File |
260 | RelativePath=".\llmediamoviebase.h" | 260 | RelativePath=".\llmediamoviebase.h" |
261 | > | 261 | > |
262 | </File> | 262 | </File> |
263 | </Filter> | 263 | </Filter> |
264 | <Filter | 264 | <Filter |
265 | Name="Header Files" | 265 | Name="Header Files" |
266 | Filter="h;hpp;hxx;hm;inl;inc;xsd" | 266 | Filter="h;hpp;hxx;hm;inl;inc;xsd" |
267 | UniqueIdentifier="{D188664C-B9B7-4982-8C4B-8D9A44B4D9EF}" | 267 | UniqueIdentifier="{D188664C-B9B7-4982-8C4B-8D9A44B4D9EF}" |
268 | > | 268 | > |
269 | <File | 269 | <File |
270 | RelativePath=".\llmediabase.h" | 270 | RelativePath=".\llmediabase.h" |
271 | > | 271 | > |
272 | </File> | 272 | </File> |
273 | <File | 273 | <File |
274 | RelativePath=".\llmediaemitter.h" | 274 | RelativePath=".\llmediaemitter.h" |
275 | > | 275 | > |
276 | </File> | 276 | </File> |
277 | <File | 277 | <File |
278 | RelativePath=".\llmediaemitterevents.h" | 278 | RelativePath=".\llmediaemitterevents.h" |
279 | > | 279 | > |
280 | </File> | 280 | </File> |
281 | <File | 281 | <File |
282 | RelativePath=".\llmediaengine.h" | 282 | RelativePath=".\llmediaengine.h" |
283 | > | 283 | > |
284 | </File> | 284 | </File> |
285 | <File | 285 | <File |
286 | RelativePath=".\llmediaimplquicktime.h" | 286 | RelativePath=".\llmediaimplquicktime.h" |
287 | > | 287 | > |
288 | </File> | 288 | </File> |
289 | <File | 289 | <File |
290 | RelativePath=".\llmediaobservers.h" | 290 | RelativePath=".\llmediaobservers.h" |
291 | > | 291 | > |
292 | </File> | 292 | </File> |
293 | </Filter> | 293 | </Filter> |
294 | </Files> | 294 | </Files> |
295 | <Globals> | 295 | <Globals> |
296 | </Globals> | 296 | </Globals> |
297 | </VisualStudioProject> | 297 | </VisualStudioProject> |
diff --git a/linden/indra/llmedia/llmediabase.cpp b/linden/indra/llmedia/llmediabase.cpp index 7abf960..17bb563 100644 --- a/linden/indra/llmedia/llmediabase.cpp +++ b/linden/indra/llmedia/llmediabase.cpp | |||
@@ -30,6 +30,7 @@ | |||
30 | 30 | ||
31 | #include "llmediabase.h" | 31 | #include "llmediabase.h" |
32 | #include "llmediaimplquicktime.h" | 32 | #include "llmediaimplquicktime.h" |
33 | #include "llmediaimplgstreamer.h" | ||
33 | 34 | ||
34 | LLMediaBase::LLMediaBase() : | 35 | LLMediaBase::LLMediaBase() : |
35 | mBufferChangeCount ( 1 ), | 36 | mBufferChangeCount ( 1 ), |
@@ -60,6 +61,13 @@ LLMediaBase* LLMediaBase::make( const MediaType mediaTypeIn, S32 width_pixels, S | |||
60 | } | 61 | } |
61 | else | 62 | else |
62 | #endif | 63 | #endif |
64 | #if LL_GSTREAMER_ENABLED | ||
65 | if ( mediaTypeIn == QuickTime ) | ||
66 | { | ||
67 | return new LLMediaImplGStreamer (); | ||
68 | } | ||
69 | else | ||
70 | #endif | ||
63 | 71 | ||
64 | return 0; | 72 | return 0; |
65 | } | 73 | } |
diff --git a/linden/indra/llmedia/llmediaimplgstreamer.cpp b/linden/indra/llmedia/llmediaimplgstreamer.cpp new file mode 100644 index 0000000..f8b4c74 --- /dev/null +++ b/linden/indra/llmedia/llmediaimplgstreamer.cpp | |||
@@ -0,0 +1,715 @@ | |||
1 | /** | ||
2 | * @file llmediaimplgstreamer.cpp | ||
3 | * @brief implementation that supports various media through GStreamer. | ||
4 | * | ||
5 | * Copyright (c) 2007-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * Second Life Viewer Source Code | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | #include "linden_common.h" | ||
30 | |||
31 | #if LL_GSTREAMER_ENABLED | ||
32 | |||
33 | extern "C" { | ||
34 | #include <gst/gst.h> | ||
35 | } | ||
36 | |||
37 | #include "llmediaimplgstreamer.h" | ||
38 | |||
39 | #include "llmediaimplgstreamervidplug.h" | ||
40 | |||
41 | #ifdef LL_GST_SOUNDSINK | ||
42 | #include "llmediaimplgstreamersndplug.h" | ||
43 | #endif // LL_GST_SOUNDSINK | ||
44 | |||
45 | #include "llmediaimplgstreamer_syms.h" | ||
46 | |||
47 | #include "llgl.h" | ||
48 | #include "llglheaders.h" // For gl texture modes | ||
49 | |||
50 | /////////////////////////////////////////////////////////////////////////////// | ||
51 | // | ||
52 | LLMediaImplGStreamer:: | ||
53 | LLMediaImplGStreamer () : | ||
54 | mediaData ( NULL ), | ||
55 | ownBuffer ( TRUE ), | ||
56 | mVolume ( 1.0f ), | ||
57 | currentMode ( ModeIdle ), | ||
58 | mPump ( NULL ), | ||
59 | mPlaybin ( NULL ), | ||
60 | mVideoSink ( NULL ) | ||
61 | #ifdef LL_GST_SOUNDSINK | ||
62 | ,mAudioSink ( NULL ) | ||
63 | #endif // LL_GST_SOUNDSINK | ||
64 | { | ||
65 | mMediaDepthBytes = 4; | ||
66 | mTextureDepth = 4; | ||
67 | mTextureFormatInternal = GL_RGB8; | ||
68 | mTextureFormatPrimary = GL_BGRA; | ||
69 | mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV; | ||
70 | } | ||
71 | |||
72 | /////////////////////////////////////////////////////////////////////////////// | ||
73 | // | ||
74 | LLMediaImplGStreamer:: | ||
75 | ~LLMediaImplGStreamer () | ||
76 | { | ||
77 | unload(); | ||
78 | } | ||
79 | |||
80 | void UnloadGStreamer() | ||
81 | { | ||
82 | ungrab_gst_syms(); | ||
83 | } | ||
84 | |||
85 | |||
86 | /////////////////////////////////////////////////////////////////////////////// | ||
87 | // | ||
88 | BOOL | ||
89 | LLMediaImplGStreamer:: | ||
90 | setBuffer ( U8* bufferIn ) | ||
91 | { | ||
92 | // Since we've pointed GStreamer at the old media data buffer | ||
93 | // directly, we need to be somewhat careful deleting it... | ||
94 | U8* oldMediaData = mediaData; | ||
95 | BOOL ownedMediaData = ownBuffer; | ||
96 | |||
97 | if(bufferIn == NULL) | ||
98 | { | ||
99 | // Passing NULL to this function requests that the object | ||
100 | // allocate its own buffer. | ||
101 | mediaData = new unsigned char[ mMediaHeight * mMediaRowbytes ]; | ||
102 | ownBuffer = TRUE; | ||
103 | } | ||
104 | else | ||
105 | { | ||
106 | // Use the supplied buffer. | ||
107 | mediaData = bufferIn; | ||
108 | ownBuffer = FALSE; | ||
109 | } | ||
110 | |||
111 | if(mediaData == NULL) | ||
112 | { | ||
113 | // This is bad - probably out of memory. | ||
114 | llerrs << "LLMediaImplGStreamer::setBuffer: mediaData is NULL" << llendl; | ||
115 | // NOTE: This case doesn't clean up properly. This assert is fatal, so this isn't a huge problem, | ||
116 | // but if this assert is ever removed the code should be fixed to clean up correctly. | ||
117 | return FALSE; | ||
118 | } | ||
119 | |||
120 | // [..] | ||
121 | |||
122 | // Delete the old media data buffer iff we owned it. | ||
123 | if ( ownedMediaData ) | ||
124 | { | ||
125 | if ( oldMediaData ) | ||
126 | { | ||
127 | delete [] oldMediaData; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | return TRUE; | ||
132 | } | ||
133 | |||
134 | /////////////////////////////////////////////////////////////////////////////// | ||
135 | // | ||
136 | BOOL | ||
137 | LLMediaImplGStreamer:: | ||
138 | init () | ||
139 | { | ||
140 | static bool done_init = false; | ||
141 | if (!done_init) | ||
142 | { | ||
143 | // Get symbols! | ||
144 | if (! grab_gst_syms("libgstreamer-0.10.so.0", | ||
145 | "libgstvideo-0.10.so.0", | ||
146 | "libgstaudio-0.10.so.0") ) | ||
147 | { | ||
148 | llwarns << "Couldn't find suitable GStreamer 0.10 support on this system - video playback disabled." << llendl; | ||
149 | return FALSE; | ||
150 | } | ||
151 | |||
152 | if (llgst_segtrap_set_enabled) | ||
153 | llgst_segtrap_set_enabled(FALSE); | ||
154 | else | ||
155 | llwarns << "gst_segtrap_set_enabled() is not available; Second Life automated crash-reporter may cease to function until next restart." << llendl; | ||
156 | |||
157 | if (0 == llgst_init_check(NULL, NULL, NULL)) | ||
158 | { | ||
159 | return FALSE; | ||
160 | } | ||
161 | |||
162 | // Init our custom plugins - only really need do this once. | ||
163 | gst_slvideo_init_class(); | ||
164 | #if 0 | ||
165 | gst_slsound_init_class(); | ||
166 | #endif | ||
167 | |||
168 | done_init = true; | ||
169 | } | ||
170 | |||
171 | // Create a pumpable main-loop for this media | ||
172 | mPump = g_main_loop_new (NULL, FALSE); | ||
173 | if (!mPump) | ||
174 | { | ||
175 | return FALSE; | ||
176 | } | ||
177 | |||
178 | // instantiate a playbin element to do the hard work | ||
179 | mPlaybin = llgst_element_factory_make ("playbin", "play"); | ||
180 | if (!mPlaybin) | ||
181 | { | ||
182 | // todo: cleanup pump | ||
183 | return FALSE; | ||
184 | } | ||
185 | |||
186 | if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) { | ||
187 | // instantiate and connect a custom video sink | ||
188 | mVideoSink = | ||
189 | GST_SLVIDEO(llgst_element_factory_make ("private-slvideo", "slvideo")); | ||
190 | if (!mVideoSink) | ||
191 | { | ||
192 | llwarns << "Could not instantiate private-slvideo element." | ||
193 | << llendl; | ||
194 | // todo: cleanup. | ||
195 | return FALSE; | ||
196 | } | ||
197 | |||
198 | g_object_set(mPlaybin, "video-sink", mVideoSink, NULL); | ||
199 | |||
200 | #ifdef LL_GST_SOUNDSINK | ||
201 | // instantiate and connect a custom audio sink | ||
202 | mAudioSink = | ||
203 | GST_SLSOUND(llgst_element_factory_make ("private-slsound", "slsound")); | ||
204 | if (!mAudioSink) | ||
205 | { | ||
206 | llwarns << "Could not instantiate private-slsound element." | ||
207 | << llendl; | ||
208 | // todo: cleanup. | ||
209 | return FALSE; | ||
210 | } | ||
211 | |||
212 | g_object_set(mPlaybin, "audio-sink", mAudioSink, NULL); | ||
213 | #endif | ||
214 | } | ||
215 | |||
216 | return LLMediaMovieBase::init(); | ||
217 | } | ||
218 | |||
219 | |||
220 | /////////////////////////////////////////////////////////////////////////////// | ||
221 | // | ||
222 | //#define LL_GST_REPORT_STATE_CHANGES | ||
223 | #ifdef LL_GST_REPORT_STATE_CHANGES | ||
224 | static char* get_gst_state_name(GstState state) | ||
225 | { | ||
226 | switch (state) { | ||
227 | case GST_STATE_VOID_PENDING: return "VOID_PENDING"; | ||
228 | case GST_STATE_NULL: return "NULL"; | ||
229 | case GST_STATE_READY: return "READY"; | ||
230 | case GST_STATE_PAUSED: return "PAUSED"; | ||
231 | case GST_STATE_PLAYING: return "PLAYING"; | ||
232 | } | ||
233 | return "(unknown)"; | ||
234 | } | ||
235 | #endif // LL_GST_REPORT_STATE_CHANGES | ||
236 | |||
237 | static gboolean | ||
238 | my_bus_callback (GstBus *bus, | ||
239 | GstMessage *message, | ||
240 | gpointer data) | ||
241 | { | ||
242 | if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_STATE_CHANGED && | ||
243 | GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING) | ||
244 | { | ||
245 | llinfos << "Got GST message type: " | ||
246 | << LLGST_MESSAGE_TYPE_NAME (message) | ||
247 | << llendl; | ||
248 | } | ||
249 | else | ||
250 | { | ||
251 | lldebugs << "Got GST message type: " | ||
252 | << LLGST_MESSAGE_TYPE_NAME (message) | ||
253 | << llendl; | ||
254 | } | ||
255 | |||
256 | LLMediaImplGStreamer *impl = (LLMediaImplGStreamer*)data; | ||
257 | |||
258 | switch (GST_MESSAGE_TYPE (message)) { | ||
259 | case GST_MESSAGE_BUFFERING: { | ||
260 | // NEEDS GST 0.10.11+ | ||
261 | if (llgst_message_parse_buffering) | ||
262 | { | ||
263 | gint percent = 0; | ||
264 | llgst_message_parse_buffering(message, &percent); | ||
265 | llinfos << "GST buffering: " << percent | ||
266 | << "%" << llendl; | ||
267 | // ModeBuffering seems to do nothing except make | ||
268 | // the UI worse | ||
269 | /*if (percent < 100) impl->setCurrentMode(LLMediaImplGStreamer::ModeBuffering);*/ | ||
270 | } | ||
271 | break; | ||
272 | } | ||
273 | case GST_MESSAGE_STATE_CHANGED: { | ||
274 | GstState old_state; | ||
275 | GstState new_state; | ||
276 | GstState pending_state; | ||
277 | llgst_message_parse_state_changed(message, | ||
278 | &old_state, | ||
279 | &new_state, | ||
280 | &pending_state); | ||
281 | #ifdef LL_GST_REPORT_STATE_CHANGES | ||
282 | // not generally very useful, and rather spammy. | ||
283 | llinfos << "state change (old,<new>,pending): " | ||
284 | << get_gst_state_name(old_state) << ", <" | ||
285 | << get_gst_state_name(new_state) << ">, " | ||
286 | << get_gst_state_name(pending_state) << | ||
287 | llendl; | ||
288 | #endif // LL_GST_REPORT_STATE_CHANGES | ||
289 | |||
290 | switch (new_state) { | ||
291 | case GST_STATE_VOID_PENDING: | ||
292 | impl->setCurrentMode(LLMediaImplGStreamer::ModeNone); | ||
293 | break; | ||
294 | case GST_STATE_NULL: | ||
295 | impl->setCurrentMode(LLMediaImplGStreamer::ModeNone); | ||
296 | break; | ||
297 | case GST_STATE_READY: | ||
298 | impl->setCurrentMode(LLMediaImplGStreamer::ModeStopped); | ||
299 | break; | ||
300 | case GST_STATE_PAUSED: | ||
301 | impl->setCurrentMode(LLMediaImplGStreamer::ModePaused); | ||
302 | break; | ||
303 | case GST_STATE_PLAYING: | ||
304 | impl->setCurrentMode(LLMediaImplGStreamer::ModePlaying); | ||
305 | break; | ||
306 | } | ||
307 | break; | ||
308 | } | ||
309 | case GST_MESSAGE_ERROR: { | ||
310 | GError *err; | ||
311 | gchar *debug; | ||
312 | |||
313 | llgst_message_parse_error (message, &err, &debug); | ||
314 | llinfos << "GST error: " << err->message << llendl; | ||
315 | g_error_free (err); | ||
316 | g_free (debug); | ||
317 | |||
318 | impl->setCurrentMode(LLMediaImplGStreamer::ModeError); | ||
319 | |||
320 | impl->stop(); | ||
321 | |||
322 | break; | ||
323 | } | ||
324 | case GST_MESSAGE_INFO: { | ||
325 | if (llgst_message_parse_info) | ||
326 | { | ||
327 | GError *err; | ||
328 | gchar *debug; | ||
329 | |||
330 | llgst_message_parse_info (message, &err, &debug); | ||
331 | llinfos << "GST info: " << err->message << llendl; | ||
332 | g_error_free (err); | ||
333 | g_free (debug); | ||
334 | } | ||
335 | break; | ||
336 | } | ||
337 | case GST_MESSAGE_WARNING: { | ||
338 | GError *err; | ||
339 | gchar *debug; | ||
340 | |||
341 | llgst_message_parse_warning (message, &err, &debug); | ||
342 | llinfos << "GST warning: " << err->message << llendl; | ||
343 | g_error_free (err); | ||
344 | g_free (debug); | ||
345 | |||
346 | break; | ||
347 | } | ||
348 | case GST_MESSAGE_EOS: | ||
349 | /* end-of-stream */ | ||
350 | llinfos << "GST EOS." << llendl; | ||
351 | impl->setCurrentMode(LLMediaImplGStreamer::ModeStopped);//? | ||
352 | impl->stop(); | ||
353 | break; | ||
354 | default: | ||
355 | /* unhandled message */ | ||
356 | break; | ||
357 | } | ||
358 | |||
359 | /* we want to be notified again the next time there is a message | ||
360 | * on the bus, so returning TRUE (FALSE means we want to stop watching | ||
361 | * for messages on the bus and our callback should not be called again) | ||
362 | */ | ||
363 | return TRUE; | ||
364 | } | ||
365 | |||
366 | BOOL | ||
367 | LLMediaImplGStreamer:: | ||
368 | load ( const LLString& urlIn ) | ||
369 | { | ||
370 | llinfos << "Setting media URI: " << urlIn << llendl; | ||
371 | |||
372 | // set URI | ||
373 | g_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), NULL); | ||
374 | //g_object_set (G_OBJECT (mPlaybin), "uri", "file:///tmp/movie", NULL); | ||
375 | |||
376 | // get playbin's bus - perhaps this can/should be done at init() | ||
377 | GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin)); | ||
378 | if (!bus) | ||
379 | { | ||
380 | return FALSE; | ||
381 | } | ||
382 | llgst_bus_add_watch (bus, my_bus_callback, this); | ||
383 | llgst_object_unref (bus); | ||
384 | |||
385 | if (true) // dummy values | ||
386 | { | ||
387 | const int fixedsize = 2; | ||
388 | mMediaRowbytes = mMediaDepthBytes * fixedsize; | ||
389 | mMediaWidth = fixedsize; | ||
390 | mMediaHeight = fixedsize; | ||
391 | mTextureWidth = fixedsize; | ||
392 | mTextureHeight = fixedsize; | ||
393 | } | ||
394 | |||
395 | BOOL rtn = LLMediaMovieBase::load(urlIn); | ||
396 | llinfos << "load returns " << int(rtn) << llendl; | ||
397 | return rtn; | ||
398 | } | ||
399 | |||
400 | /////////////////////////////////////////////////////////////////////////////// | ||
401 | // | ||
402 | BOOL | ||
403 | LLMediaImplGStreamer:: | ||
404 | unload () | ||
405 | { | ||
406 | if (mPlaybin) | ||
407 | { | ||
408 | llgst_element_set_state (mPlaybin, GST_STATE_NULL); | ||
409 | llgst_object_unref (GST_OBJECT (mPlaybin)); | ||
410 | mPlaybin = NULL; | ||
411 | } | ||
412 | |||
413 | if (mPump) | ||
414 | { | ||
415 | g_main_loop_quit(mPump); | ||
416 | mPump = NULL; | ||
417 | } | ||
418 | |||
419 | if (mediaData) | ||
420 | { | ||
421 | if (ownBuffer) | ||
422 | { | ||
423 | delete mediaData; | ||
424 | mediaData = NULL; | ||
425 | } | ||
426 | } | ||
427 | |||
428 | mVideoSink = NULL; | ||
429 | |||
430 | return TRUE; | ||
431 | } | ||
432 | |||
433 | /////////////////////////////////////////////////////////////////////////////// | ||
434 | // | ||
435 | S32 | ||
436 | LLMediaImplGStreamer:: | ||
437 | updateMedia () | ||
438 | { | ||
439 | //llinfos << "updating media..." << llendl; | ||
440 | if (g_main_context_pending(g_main_loop_get_context(mPump))) | ||
441 | { | ||
442 | g_main_context_iteration(g_main_loop_get_context(mPump), FALSE); | ||
443 | } | ||
444 | |||
445 | if (mVideoSink) | ||
446 | { | ||
447 | GST_OBJECT_LOCK(mVideoSink); | ||
448 | if (mVideoSink->retained_frame_ready) | ||
449 | { | ||
450 | //llinfos << "NEW FRAME " << llendl; | ||
451 | if (mVideoSink->retained_frame_width != mMediaWidth || | ||
452 | mVideoSink->retained_frame_height != mMediaHeight) | ||
453 | // *TODO: also check for change in format | ||
454 | { | ||
455 | // just resize container | ||
456 | mMediaWidth = mVideoSink->retained_frame_width; | ||
457 | mMediaHeight = mVideoSink->retained_frame_height; | ||
458 | mTextureWidth = mMediaWidth; | ||
459 | mTextureHeight = mMediaHeight; | ||
460 | mMediaDepthBytes = mTextureDepth = | ||
461 | SLVPixelFormatBytes[mVideoSink->retained_frame_format]; | ||
462 | if (SLV_PF_RGBX == mVideoSink->retained_frame_format) | ||
463 | { | ||
464 | mTextureFormatPrimary = GL_RGBA; | ||
465 | mTextureFormatType=GL_UNSIGNED_INT_8_8_8_8_REV; | ||
466 | } | ||
467 | else | ||
468 | { | ||
469 | mTextureFormatPrimary = GL_BGRA; | ||
470 | mTextureFormatType=GL_UNSIGNED_INT_8_8_8_8_REV; | ||
471 | } | ||
472 | mMediaRowbytes = mMediaWidth * mMediaDepthBytes; | ||
473 | llinfos << "video container resized to " << | ||
474 | mMediaWidth << "x" << mMediaHeight << llendl; | ||
475 | |||
476 | if (ownBuffer) | ||
477 | { | ||
478 | // we manage the buffer, so we need to realloc | ||
479 | delete[] mediaData; | ||
480 | mediaData = new U8[mMediaRowbytes * | ||
481 | mMediaHeight]; | ||
482 | } | ||
483 | |||
484 | GST_OBJECT_UNLOCK(mVideoSink); | ||
485 | return updateMediaNeedsSizeChange; | ||
486 | } | ||
487 | |||
488 | // we're gonna totally consume this frame - reset 'ready' flag | ||
489 | mVideoSink->retained_frame_ready = FALSE; | ||
490 | memcpy(mediaData, mVideoSink->retained_frame_data, | ||
491 | mMediaRowbytes * mMediaHeight); | ||
492 | |||
493 | GST_OBJECT_UNLOCK(mVideoSink); | ||
494 | return updateMediaNeedsUpdate; | ||
495 | } | ||
496 | else | ||
497 | { | ||
498 | // nothing to do yet. | ||
499 | GST_OBJECT_UNLOCK(mVideoSink); | ||
500 | return updateMediaNoChanges; | ||
501 | } | ||
502 | } | ||
503 | |||
504 | return updateMediaNoChanges; | ||
505 | } | ||
506 | |||
507 | /////////////////////////////////////////////////////////////////////////////// | ||
508 | // | ||
509 | void | ||
510 | LLMediaImplGStreamer:: | ||
511 | setAutoScaled ( BOOL autoScaledIn ) | ||
512 | { | ||
513 | autoScaled = autoScaledIn; | ||
514 | } | ||
515 | |||
516 | /////////////////////////////////////////////////////////////////////////////// | ||
517 | // | ||
518 | BOOL | ||
519 | LLMediaImplGStreamer:: | ||
520 | stop () | ||
521 | { | ||
522 | llinfos << "stopping media..." << llendl; | ||
523 | // todo: error-check this? | ||
524 | llgst_element_set_state(mPlaybin, GST_STATE_READY); | ||
525 | |||
526 | BOOL rtn = LLMediaMovieBase::stop(); | ||
527 | setCurrentMode(LLMediaImplGStreamer::ModeStopped);//? | ||
528 | return rtn; | ||
529 | } | ||
530 | |||
531 | /////////////////////////////////////////////////////////////////////////////// | ||
532 | // | ||
533 | BOOL | ||
534 | LLMediaImplGStreamer:: | ||
535 | play () | ||
536 | { | ||
537 | llinfos << "playing media..." << llendl; | ||
538 | // todo: error-check this? | ||
539 | llgst_element_set_state(mPlaybin, GST_STATE_PLAYING); | ||
540 | |||
541 | return LLMediaMovieBase::play(); | ||
542 | } | ||
543 | |||
544 | /////////////////////////////////////////////////////////////////////////////// | ||
545 | // | ||
546 | BOOL | ||
547 | LLMediaImplGStreamer:: | ||
548 | loop ( S32 howMany ) | ||
549 | { | ||
550 | llinfos << "looping media... " << howMany << llendl; | ||
551 | // todo: implement this | ||
552 | if (!play()) | ||
553 | return FALSE; | ||
554 | |||
555 | return LLMediaMovieBase::loop(howMany); | ||
556 | }; | ||
557 | |||
558 | /////////////////////////////////////////////////////////////////////////////// | ||
559 | // | ||
560 | BOOL | ||
561 | LLMediaImplGStreamer:: | ||
562 | pause () | ||
563 | { | ||
564 | llinfos << "pausing media..." << llendl; | ||
565 | // todo: error-check this? | ||
566 | llgst_element_set_state(mPlaybin, GST_STATE_PAUSED); | ||
567 | |||
568 | return LLMediaMovieBase::pause(); | ||
569 | }; | ||
570 | |||
571 | /////////////////////////////////////////////////////////////////////////////// | ||
572 | // | ||
573 | BOOL | ||
574 | LLMediaImplGStreamer:: | ||
575 | setVolume ( F32 volumeIn ) | ||
576 | { | ||
577 | mVolume = volumeIn; | ||
578 | g_object_set(mPlaybin, "volume", mVolume, NULL); | ||
579 | return TRUE; | ||
580 | } | ||
581 | |||
582 | /////////////////////////////////////////////////////////////////////////////// | ||
583 | // | ||
584 | F32 | ||
585 | LLMediaImplGStreamer:: | ||
586 | getVolume () | ||
587 | { | ||
588 | return mVolume; | ||
589 | } | ||
590 | |||
591 | /////////////////////////////////////////////////////////////////////////////// | ||
592 | // | ||
593 | BOOL | ||
594 | LLMediaImplGStreamer:: | ||
595 | isIdle () const | ||
596 | { | ||
597 | // todo: probably semantically decouple from currentMode | ||
598 | return currentMode == ModeIdle; | ||
599 | } | ||
600 | |||
601 | /////////////////////////////////////////////////////////////////////////////// | ||
602 | // | ||
603 | BOOL | ||
604 | LLMediaImplGStreamer:: | ||
605 | isError () const | ||
606 | { | ||
607 | // todo: probably semantically decouple from currentMode | ||
608 | return currentMode == ModeError; | ||
609 | } | ||
610 | |||
611 | /////////////////////////////////////////////////////////////////////////////// | ||
612 | // | ||
613 | BOOL | ||
614 | LLMediaImplGStreamer:: | ||
615 | isBuffering () const | ||
616 | { | ||
617 | // todo: probably semantically decouple from currentMode | ||
618 | return currentMode == ModeBuffering; | ||
619 | } | ||
620 | |||
621 | /////////////////////////////////////////////////////////////////////////////// | ||
622 | // | ||
623 | BOOL | ||
624 | LLMediaImplGStreamer:: | ||
625 | isLoaded () const | ||
626 | { | ||
627 | // todo: probably semantically decouple from currentMode | ||
628 | //return currentMode == ModeLoaded; | ||
629 | return (mPump != NULL); | ||
630 | } | ||
631 | |||
632 | /////////////////////////////////////////////////////////////////////////////// | ||
633 | // | ||
634 | BOOL | ||
635 | LLMediaImplGStreamer:: | ||
636 | isPlaying () const | ||
637 | { | ||
638 | // todo: probably semantically decouple from currentMode | ||
639 | return currentMode == ModePlaying; | ||
640 | } | ||
641 | |||
642 | /////////////////////////////////////////////////////////////////////////////// | ||
643 | // | ||
644 | BOOL | ||
645 | LLMediaImplGStreamer:: | ||
646 | isLooping () const | ||
647 | { | ||
648 | // todo: probably semantically decouple from currentMode | ||
649 | return currentMode == ModeLooping; | ||
650 | } | ||
651 | |||
652 | /////////////////////////////////////////////////////////////////////////////// | ||
653 | // | ||
654 | BOOL | ||
655 | LLMediaImplGStreamer:: | ||
656 | isPaused () const | ||
657 | { | ||
658 | // todo: probably semantically decouple from currentMode | ||
659 | return currentMode == ModePaused; | ||
660 | } | ||
661 | |||
662 | /////////////////////////////////////////////////////////////////////////////// | ||
663 | // | ||
664 | BOOL | ||
665 | LLMediaImplGStreamer:: | ||
666 | isStopped () const | ||
667 | { | ||
668 | // todo: probably semantically decouple from currentMode | ||
669 | return currentMode == ModeStopped; | ||
670 | } | ||
671 | |||
672 | /////////////////////////////////////////////////////////////////////////////// | ||
673 | // | ||
674 | U8* | ||
675 | LLMediaImplGStreamer:: | ||
676 | getMediaData () | ||
677 | { | ||
678 | return mediaData; | ||
679 | } | ||
680 | |||
681 | /////////////////////////////////////////////////////////////////////////////// | ||
682 | // | ||
683 | BOOL | ||
684 | LLMediaImplGStreamer:: | ||
685 | seek ( F64 time ) | ||
686 | { | ||
687 | // todo: implement this | ||
688 | llinfos << "Tried to seek to time " << time | ||
689 | << " - faking it" << llendl; | ||
690 | return TRUE; | ||
691 | } | ||
692 | |||
693 | /////////////////////////////////////////////////////////////////////////////// | ||
694 | // | ||
695 | F64 | ||
696 | LLMediaImplGStreamer:: | ||
697 | getTime () const | ||
698 | { | ||
699 | // todo: implement this | ||
700 | F64 result = 0; | ||
701 | return result; | ||
702 | } | ||
703 | |||
704 | /////////////////////////////////////////////////////////////////////////////// | ||
705 | // | ||
706 | F64 | ||
707 | LLMediaImplGStreamer:: | ||
708 | getMediaDuration () const | ||
709 | { | ||
710 | // todo: implement this | ||
711 | F64 result = 0; | ||
712 | return result; | ||
713 | } | ||
714 | |||
715 | #endif // LL_GSTREAMER_ENABLED | ||
diff --git a/linden/indra/llmedia/llmediaimplgstreamer.h b/linden/indra/llmedia/llmediaimplgstreamer.h new file mode 100644 index 0000000..52a5c84 --- /dev/null +++ b/linden/indra/llmedia/llmediaimplgstreamer.h | |||
@@ -0,0 +1,126 @@ | |||
1 | /** | ||
2 | * @file llmediaimplgstreamer.h | ||
3 | * @brief implementation that supports media playback via GStreamer. | ||
4 | * | ||
5 | * Copyright (c) 2007-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * Second Life Viewer Source Code | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | // header guard | ||
30 | #ifndef llmediaimplgstreamer_h | ||
31 | #define llmediaimplgstreamer_h | ||
32 | |||
33 | #if LL_GSTREAMER_ENABLED | ||
34 | |||
35 | extern "C" { | ||
36 | #include <gst/gst.h> | ||
37 | |||
38 | #include <apr-1/apr_pools.h> | ||
39 | #include <apr-1/apr_dso.h> | ||
40 | } | ||
41 | |||
42 | #include "stdtypes.h" | ||
43 | |||
44 | #include "llmediamoviebase.h" | ||
45 | |||
46 | #include "llmediaimplgstreamervidplug.h" | ||
47 | #ifdef LL_GST_SOUNDSINK | ||
48 | #include "llmediaimplgstreamersndplug.h" | ||
49 | #endif // LL_GST_SOUNDSINK | ||
50 | |||
51 | /////////////////////////////////////////////////////////////////////////// | ||
52 | class LLMediaImplGStreamer: | ||
53 | public LLMediaMovieBase | ||
54 | { | ||
55 | public: | ||
56 | LLMediaImplGStreamer (); | ||
57 | virtual ~LLMediaImplGStreamer (); | ||
58 | |||
59 | //////////////////////////////////////////////////////// | ||
60 | // implementation of the media public interface | ||
61 | |||
62 | // housekeeping | ||
63 | virtual BOOL setBuffer ( U8* bufferIn ); | ||
64 | virtual BOOL init (); | ||
65 | virtual BOOL load ( const LLString& urlIn ); | ||
66 | virtual BOOL unload (); | ||
67 | |||
68 | // transport controls | ||
69 | virtual BOOL stop (); | ||
70 | virtual BOOL play (); | ||
71 | virtual BOOL loop ( S32 howMany ); | ||
72 | virtual BOOL pause (); | ||
73 | virtual BOOL seek ( F64 time ); | ||
74 | |||
75 | // audio levels | ||
76 | virtual BOOL setVolume ( F32 volumeIn ); | ||
77 | virtual F32 getVolume (); | ||
78 | |||
79 | // status | ||
80 | virtual BOOL isIdle () const; | ||
81 | virtual BOOL isBuffering () const; | ||
82 | virtual BOOL isError () const; | ||
83 | virtual BOOL isLoaded () const; | ||
84 | virtual BOOL isStopped () const; | ||
85 | virtual BOOL isPaused () const; | ||
86 | virtual BOOL isPlaying () const; | ||
87 | virtual BOOL isLooping () const; | ||
88 | virtual F64 getTime () const; | ||
89 | |||
90 | // media data | ||
91 | virtual S32 updateMedia (); | ||
92 | virtual void setAutoScaled ( BOOL autoScaledIn ); | ||
93 | virtual U8* getMediaData (); | ||
94 | virtual F64 getMediaDuration () const; | ||
95 | |||
96 | // class-specific | ||
97 | GMainLoop *getPump() {return mPump;}; | ||
98 | typedef enum { ModeNone, ModeIdle, ModeError, ModeBuffering, ModeStopped, ModePaused, ModePlaying, ModeLooping } llGstMode; | ||
99 | llGstMode getCurrentMode() {return currentMode;}; | ||
100 | void setCurrentMode(llGstMode mode) {currentMode = mode;}; | ||
101 | |||
102 | private: | ||
103 | // misc | ||
104 | U8* mediaData; | ||
105 | BOOL ownBuffer; | ||
106 | BOOL autoScaled; | ||
107 | F32 mVolume; | ||
108 | |||
109 | llGstMode currentMode; | ||
110 | |||
111 | // GStreamer-specific | ||
112 | GMainLoop *mPump; // event pump for this media | ||
113 | GstElement *mPlaybin; | ||
114 | GstSLVideo *mVideoSink; | ||
115 | #ifdef LL_GST_SOUNDSINK | ||
116 | GstSLSound *mAudioSink; | ||
117 | #endif // LL_GST_SOUNDSINK | ||
118 | }; | ||
119 | |||
120 | // called during shutdown when no instances may exist | ||
121 | void UnloadGStreamer(); | ||
122 | |||
123 | |||
124 | #endif // LL_GSTREAMER_ENABLED | ||
125 | |||
126 | #endif // llmediaimplgstreamer_h | ||
diff --git a/linden/indra/llmedia/llmediaimplgstreamer_syms.cpp b/linden/indra/llmedia/llmediaimplgstreamer_syms.cpp new file mode 100644 index 0000000..76f62e1 --- /dev/null +++ b/linden/indra/llmedia/llmediaimplgstreamer_syms.cpp | |||
@@ -0,0 +1,189 @@ | |||
1 | /** | ||
2 | * @file llmediaimplgstreamer_syms.cpp | ||
3 | * @brief dynamic GStreamer symbol-grabbing code | ||
4 | * | ||
5 | * Copyright (c) 2007-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * Second Life Viewer Source Code | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | #include "linden_common.h" | ||
30 | |||
31 | #if LL_GSTREAMER_ENABLED | ||
32 | |||
33 | extern "C" { | ||
34 | #include <gst/gst.h> | ||
35 | |||
36 | #include <apr-1/apr_pools.h> | ||
37 | #include <apr-1/apr_dso.h> | ||
38 | } | ||
39 | |||
40 | #include "llmediaimplgstreamer.h" | ||
41 | |||
42 | #define LL_GST_SYM(REQ, GSTSYM, RTN, ...) RTN (*ll##GSTSYM)(__VA_ARGS__) = NULL | ||
43 | #include "llmediaimplgstreamer_syms_raw.inc" | ||
44 | #include "llmediaimplgstreamer_syms_rawa.inc" | ||
45 | #include "llmediaimplgstreamer_syms_rawv.inc" | ||
46 | #undef LL_GST_SYM | ||
47 | |||
48 | |||
49 | static bool sSymsGrabbed = false; | ||
50 | static apr_pool_t *sSymGSTDSOMemoryPool = NULL; | ||
51 | static apr_dso_handle_t *sSymGSTDSOHandleG = NULL; | ||
52 | static apr_dso_handle_t *sSymGSTDSOHandleV = NULL; | ||
53 | static apr_dso_handle_t *sSymGSTDSOHandleA = NULL; | ||
54 | |||
55 | |||
56 | bool grab_gst_syms(std::string gst_dso_name, | ||
57 | std::string gst_dso_name_vid, | ||
58 | std::string gst_dso_name_aud) | ||
59 | { | ||
60 | if (sSymsGrabbed) | ||
61 | { | ||
62 | // already have grabbed good syms | ||
63 | return TRUE; | ||
64 | } | ||
65 | |||
66 | bool sym_error = false; | ||
67 | bool rtn = false; | ||
68 | apr_status_t rv; | ||
69 | apr_dso_handle_t *sSymGSTDSOHandle = NULL; | ||
70 | |||
71 | #define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##GSTSYM, sSymGSTDSOHandle, #GSTSYM); if (rv != APR_SUCCESS) {llwarns << "Failed to grab symbol: " << #GSTSYM << llendl; if (REQ) sym_error = true;} else llinfos << "grabbed symbol: " << #GSTSYM << " from " << (void*)ll##GSTSYM << llendl;}while(0) | ||
72 | |||
73 | //attempt to load the shared libraries | ||
74 | apr_pool_create(&sSymGSTDSOMemoryPool, NULL); | ||
75 | |||
76 | if ( APR_SUCCESS == (rv = apr_dso_load(&sSymGSTDSOHandle, | ||
77 | gst_dso_name.c_str(), | ||
78 | sSymGSTDSOMemoryPool) )) | ||
79 | { | ||
80 | llinfos << "Found DSO: " << gst_dso_name << llendl; | ||
81 | #include "llmediaimplgstreamer_syms_raw.inc" | ||
82 | |||
83 | if ( sSymGSTDSOHandle ) | ||
84 | { | ||
85 | sSymGSTDSOHandleG = sSymGSTDSOHandle; | ||
86 | sSymGSTDSOHandle = NULL; | ||
87 | } | ||
88 | |||
89 | if ( APR_SUCCESS == (rv = apr_dso_load(&sSymGSTDSOHandle, | ||
90 | gst_dso_name_aud.c_str(), | ||
91 | sSymGSTDSOMemoryPool) )) | ||
92 | { | ||
93 | llinfos << "Found DSO: " << gst_dso_name_aud << llendl; | ||
94 | #include "llmediaimplgstreamer_syms_rawa.inc" | ||
95 | |||
96 | if ( sSymGSTDSOHandle ) | ||
97 | { | ||
98 | sSymGSTDSOHandleA = sSymGSTDSOHandle; | ||
99 | sSymGSTDSOHandle = NULL; | ||
100 | } | ||
101 | |||
102 | if ( APR_SUCCESS == | ||
103 | (rv = apr_dso_load(&sSymGSTDSOHandle, | ||
104 | gst_dso_name_vid.c_str(), | ||
105 | sSymGSTDSOMemoryPool) )) | ||
106 | { | ||
107 | llinfos << "Found DSO: " << gst_dso_name_vid << llendl; | ||
108 | #include "llmediaimplgstreamer_syms_rawv.inc" | ||
109 | } | ||
110 | else | ||
111 | { | ||
112 | llwarns << "Couldn't load DSO: " | ||
113 | << gst_dso_name_vid << llendl; | ||
114 | rtn = false; // failure | ||
115 | } | ||
116 | } | ||
117 | else | ||
118 | { | ||
119 | llwarns << "Couldn't load DSO: " | ||
120 | << gst_dso_name_aud << llendl; | ||
121 | rtn = false; // failure | ||
122 | } | ||
123 | |||
124 | rtn = !sym_error; | ||
125 | } | ||
126 | else | ||
127 | { | ||
128 | llwarns << "Couldn't load DSO: " << gst_dso_name << llendl; | ||
129 | rtn = false; // failure | ||
130 | } | ||
131 | |||
132 | if (sym_error) | ||
133 | { | ||
134 | llwarns << "Failed to find necessary symbols in GStreamer libraries." << llendl; | ||
135 | } | ||
136 | |||
137 | if ( sSymGSTDSOHandle ) | ||
138 | { | ||
139 | sSymGSTDSOHandleV = sSymGSTDSOHandle; | ||
140 | sSymGSTDSOHandle = NULL; | ||
141 | } | ||
142 | #undef LL_GST_SYM | ||
143 | |||
144 | sSymsGrabbed = !!rtn; | ||
145 | return rtn; | ||
146 | } | ||
147 | |||
148 | |||
149 | void ungrab_gst_syms() | ||
150 | { | ||
151 | // should be safe to call regardless of whether we've | ||
152 | // actually grabbed syms. | ||
153 | |||
154 | if ( sSymGSTDSOHandleG ) | ||
155 | { | ||
156 | apr_dso_unload(sSymGSTDSOHandleG); | ||
157 | sSymGSTDSOHandleG = NULL; | ||
158 | } | ||
159 | |||
160 | if ( sSymGSTDSOHandleA ) | ||
161 | { | ||
162 | apr_dso_unload(sSymGSTDSOHandleA); | ||
163 | sSymGSTDSOHandleA = NULL; | ||
164 | } | ||
165 | |||
166 | if ( sSymGSTDSOHandleV ) | ||
167 | { | ||
168 | apr_dso_unload(sSymGSTDSOHandleV); | ||
169 | sSymGSTDSOHandleV = NULL; | ||
170 | } | ||
171 | |||
172 | if ( sSymGSTDSOMemoryPool ) | ||
173 | { | ||
174 | apr_pool_destroy(sSymGSTDSOMemoryPool); | ||
175 | sSymGSTDSOMemoryPool = NULL; | ||
176 | } | ||
177 | |||
178 | // NULL-out all of the symbols we'd grabbed | ||
179 | #define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{ll##GSTSYM = NULL;}while(0) | ||
180 | #include "llmediaimplgstreamer_syms_raw.inc" | ||
181 | #include "llmediaimplgstreamer_syms_rawa.inc" | ||
182 | #include "llmediaimplgstreamer_syms_rawv.inc" | ||
183 | #undef LL_GST_SYM | ||
184 | |||
185 | sSymsGrabbed = false; | ||
186 | } | ||
187 | |||
188 | |||
189 | #endif // LL_GSTREAMER_ENABLED | ||
diff --git a/linden/indra/llmedia/llmediaimplgstreamer_syms.h b/linden/indra/llmedia/llmediaimplgstreamer_syms.h new file mode 100644 index 0000000..6dec2a2 --- /dev/null +++ b/linden/indra/llmedia/llmediaimplgstreamer_syms.h | |||
@@ -0,0 +1,75 @@ | |||
1 | /** | ||
2 | * @file llmediaimplgstreamer_syms.h | ||
3 | * @brief dynamic GStreamer symbol-grabbing code | ||
4 | * | ||
5 | * Copyright (c) 2007-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * Second Life Viewer Source Code | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | #include "linden_common.h" | ||
30 | |||
31 | #if LL_GSTREAMER_ENABLED | ||
32 | |||
33 | extern "C" { | ||
34 | #include <gst/gst.h> | ||
35 | } | ||
36 | |||
37 | bool grab_gst_syms(std::string gst_dso_name, | ||
38 | std::string gst_dso_name_vid, | ||
39 | std::string gst_dso_name_aud); | ||
40 | void ungrab_gst_syms(); | ||
41 | |||
42 | #define LL_GST_SYM(REQ, GSTSYM, RTN, ...) extern RTN (*ll##GSTSYM)(__VA_ARGS__) | ||
43 | #include "llmediaimplgstreamer_syms_raw.inc" | ||
44 | #include "llmediaimplgstreamer_syms_rawa.inc" | ||
45 | #include "llmediaimplgstreamer_syms_rawv.inc" | ||
46 | #undef LL_GST_SYM | ||
47 | |||
48 | // regrettable hacks to give us better runtime compatibility with older systems | ||
49 | #define llg_return_if_fail(COND) do{if (!(COND)) return;}while(0) | ||
50 | #define llg_return_val_if_fail(COND,V) do{if (!(COND)) return V;}while(0) | ||
51 | |||
52 | // regrettable hacks because GStreamer was not designed for runtime loading | ||
53 | #undef GST_TYPE_MESSAGE | ||
54 | #define GST_TYPE_MESSAGE (llgst_message_get_type()) | ||
55 | #undef GST_TYPE_OBJECT | ||
56 | #define GST_TYPE_OBJECT (llgst_object_get_type()) | ||
57 | #undef GST_TYPE_PIPELINE | ||
58 | #define GST_TYPE_PIPELINE (llgst_pipeline_get_type()) | ||
59 | #undef GST_TYPE_ELEMENT | ||
60 | #define GST_TYPE_ELEMENT (llgst_element_get_type()) | ||
61 | #undef GST_TYPE_AUDIO_SINK | ||
62 | #define GST_TYPE_AUDIO_SINK (llgst_audio_sink_get_type()) | ||
63 | #undef GST_TYPE_VIDEO_SINK | ||
64 | #define GST_TYPE_VIDEO_SINK (llgst_video_sink_get_type()) | ||
65 | #undef _gst_debug_register_funcptr | ||
66 | #define _gst_debug_register_funcptr ll_gst_debug_register_funcptr | ||
67 | #undef _gst_debug_category_new | ||
68 | #define _gst_debug_category_new ll_gst_debug_category_new | ||
69 | #undef __gst_debug_enabled | ||
70 | #define __gst_debug_enabled (0) | ||
71 | |||
72 | // more hacks | ||
73 | #define LLGST_MESSAGE_TYPE_NAME(M) (llgst_message_type_get_name(GST_MESSAGE_TYPE(M))) | ||
74 | |||
75 | #endif // LL_GSTREAMER_ENABLED | ||
diff --git a/linden/indra/llmedia/llmediaimplgstreamer_syms_raw.inc b/linden/indra/llmedia/llmediaimplgstreamer_syms_raw.inc new file mode 100644 index 0000000..c00947f --- /dev/null +++ b/linden/indra/llmedia/llmediaimplgstreamer_syms_raw.inc | |||
@@ -0,0 +1,42 @@ | |||
1 | |||
2 | // required symbols to grab | ||
3 | LL_GST_SYM(true, gst_init_check, gboolean, int *argc, char **argv[], GError ** err); | ||
4 | LL_GST_SYM(true, gst_message_get_type, GType, void); | ||
5 | LL_GST_SYM(true, gst_message_type_get_name, const gchar*, GstMessageType type); | ||
6 | LL_GST_SYM(true, gst_message_parse_error, void, GstMessage *message, GError **gerror, gchar **debug); | ||
7 | LL_GST_SYM(true, gst_message_parse_warning, void, GstMessage *message, GError **gerror, gchar **debug); | ||
8 | LL_GST_SYM(true, gst_message_parse_state_changed, void, GstMessage *message, GstState *oldstate, GstState *newstate, GstState *pending); | ||
9 | LL_GST_SYM(true, gst_element_set_state, GstStateChangeReturn, GstElement *element, GstState state); | ||
10 | LL_GST_SYM(true, gst_object_unref, void, gpointer object); | ||
11 | LL_GST_SYM(true, gst_object_get_type, GType, void); | ||
12 | LL_GST_SYM(true, gst_pipeline_get_type, GType, void); | ||
13 | LL_GST_SYM(true, gst_pipeline_get_bus, GstBus*, GstPipeline *pipeline); | ||
14 | LL_GST_SYM(true, gst_bus_add_watch, guint, GstBus * bus, GstBusFunc func, gpointer user_data); | ||
15 | LL_GST_SYM(true, gst_element_factory_make, GstElement*, const gchar *factoryname, const gchar *name); | ||
16 | LL_GST_SYM(true, gst_element_get_type, GType, void); | ||
17 | LL_GST_SYM(true, gst_static_pad_template_get, GstPadTemplate*, GstStaticPadTemplate *pad_template); | ||
18 | LL_GST_SYM(true, gst_element_class_add_pad_template, void, GstElementClass *klass, GstPadTemplate *temp); | ||
19 | LL_GST_SYM(true, gst_element_class_set_details, void, GstElementClass *klass, const GstElementDetails *details); | ||
20 | LL_GST_SYM(true, gst_caps_unref, void, GstCaps* caps); | ||
21 | LL_GST_SYM(true, gst_caps_ref, GstCaps *, GstCaps* caps); | ||
22 | LL_GST_SYM(true, _gst_debug_register_funcptr, void, GstDebugFuncPtr func, gchar* ptrname); | ||
23 | LL_GST_SYM(true, _gst_debug_category_new, GstDebugCategory *, gchar *name, guint color, gchar *description); | ||
24 | LL_GST_SYM(true, gst_caps_is_empty, gboolean, const GstCaps *caps); | ||
25 | LL_GST_SYM(true, gst_caps_from_string, GstCaps *, const gchar *string); | ||
26 | LL_GST_SYM(true, gst_caps_replace, void, GstCaps **caps, GstCaps *newcaps); | ||
27 | LL_GST_SYM(true, gst_caps_get_structure, GstStructure *, const GstCaps *caps, guint index); | ||
28 | LL_GST_SYM(true, gst_caps_copy, GstCaps *, const GstCaps * caps); | ||
29 | LL_GST_SYM(true, gst_caps_intersect, GstCaps *, const GstCaps *caps1, const GstCaps *caps2); | ||
30 | LL_GST_SYM(true, gst_element_register, gboolean, GstPlugin *plugin, const gchar *name, guint rank, GType type); | ||
31 | LL_GST_SYM(true, _gst_plugin_register_static, void, GstPluginDesc *desc); | ||
32 | LL_GST_SYM(true, gst_structure_get_int, gboolean, const GstStructure *structure, const gchar *fieldname, gint *value); | ||
33 | LL_GST_SYM(true, gst_structure_get_value, G_CONST_RETURN GValue *, const GstStructure *structure, const gchar *fieldname); | ||
34 | LL_GST_SYM(true, gst_value_get_fraction_numerator, gint, const GValue *value); | ||
35 | LL_GST_SYM(true, gst_value_get_fraction_denominator, gint, const GValue *value); | ||
36 | LL_GST_SYM(true, gst_structure_get_name, G_CONST_RETURN gchar *, const GstStructure *structure); | ||
37 | |||
38 | // optional symbols to grab | ||
39 | LL_GST_SYM(false, gst_segtrap_set_enabled, void, gboolean enabled); | ||
40 | LL_GST_SYM(false, gst_message_parse_buffering, void, GstMessage *message, gint *percent); | ||
41 | LL_GST_SYM(false, expected_to_be_missing, void, gboolean enabled); | ||
42 | LL_GST_SYM(false, gst_message_parse_info, void, GstMessage *message, GError **gerror, gchar **debug); | ||
diff --git a/linden/indra/llmedia/llmediaimplgstreamer_syms_rawa.inc b/linden/indra/llmedia/llmediaimplgstreamer_syms_rawa.inc new file mode 100644 index 0000000..0be99b5 --- /dev/null +++ b/linden/indra/llmedia/llmediaimplgstreamer_syms_rawa.inc | |||
@@ -0,0 +1,5 @@ | |||
1 | |||
2 | // required symbols to grab | ||
3 | LL_GST_SYM(true, gst_audio_sink_get_type, GType, void); | ||
4 | |||
5 | // optional symbols to grab | ||
diff --git a/linden/indra/llmedia/llmediaimplgstreamer_syms_rawv.inc b/linden/indra/llmedia/llmediaimplgstreamer_syms_rawv.inc new file mode 100644 index 0000000..14fbcb4 --- /dev/null +++ b/linden/indra/llmedia/llmediaimplgstreamer_syms_rawv.inc | |||
@@ -0,0 +1,5 @@ | |||
1 | |||
2 | // required symbols to grab | ||
3 | LL_GST_SYM(true, gst_video_sink_get_type, GType, void); | ||
4 | |||
5 | // optional symbols to grab | ||
diff --git a/linden/indra/llmedia/llmediaimplgstreamervidplug.cpp b/linden/indra/llmedia/llmediaimplgstreamervidplug.cpp new file mode 100644 index 0000000..dade946 --- /dev/null +++ b/linden/indra/llmedia/llmediaimplgstreamervidplug.cpp | |||
@@ -0,0 +1,461 @@ | |||
1 | /** | ||
2 | * @file llmediaimplgstreamervidplug.h | ||
3 | * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl | ||
4 | * | ||
5 | * Copyright (c) 2007-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * Second Life Viewer Source Code | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | #if LL_GSTREAMER_ENABLED | ||
30 | |||
31 | #include <string.h> | ||
32 | |||
33 | #include <gst/gst.h> | ||
34 | #include <gst/video/video.h> | ||
35 | #include <gst/video/gstvideosink.h> | ||
36 | |||
37 | #include "llmediaimplgstreamer_syms.h" | ||
38 | |||
39 | #include "llthread.h" | ||
40 | |||
41 | #include "llmediaimplgstreamervidplug.h" | ||
42 | |||
43 | GST_DEBUG_CATEGORY_STATIC (gst_slvideo_debug); | ||
44 | #define GST_CAT_DEFAULT gst_slvideo_debug | ||
45 | |||
46 | /* Filter signals and args */ | ||
47 | enum | ||
48 | { | ||
49 | /* FILL ME */ | ||
50 | LAST_SIGNAL | ||
51 | }; | ||
52 | |||
53 | enum | ||
54 | { | ||
55 | ARG_0 | ||
56 | }; | ||
57 | |||
58 | #define SLV_SIZECAPS ", width=(int){1,2,4,8,16,32,64,128,256,512,1024}, height=(int){1,2,4,8,16,32,64,128,256,512,1024} " | ||
59 | #define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS ";" GST_VIDEO_CAPS_BGRx SLV_SIZECAPS | ||
60 | |||
61 | static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ( | ||
62 | "sink", | ||
63 | GST_PAD_SINK, | ||
64 | GST_PAD_ALWAYS, | ||
65 | GST_STATIC_CAPS (SLV_ALLCAPS) | ||
66 | ); | ||
67 | |||
68 | GST_BOILERPLATE (GstSLVideo, gst_slvideo, GstVideoSink, | ||
69 | GST_TYPE_VIDEO_SINK); | ||
70 | |||
71 | static void gst_slvideo_set_property (GObject * object, guint prop_id, | ||
72 | const GValue * value, | ||
73 | GParamSpec * pspec); | ||
74 | static void gst_slvideo_get_property (GObject * object, guint prop_id, | ||
75 | GValue * value, GParamSpec * pspec); | ||
76 | |||
77 | static void | ||
78 | gst_slvideo_base_init (gpointer gclass) | ||
79 | { | ||
80 | static GstElementDetails element_details = { | ||
81 | "PluginTemplate", | ||
82 | "Generic/PluginTemplate", | ||
83 | "Generic Template Element", | ||
84 | "Linden Lab" | ||
85 | }; | ||
86 | GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); | ||
87 | |||
88 | llgst_element_class_add_pad_template (element_class, | ||
89 | llgst_static_pad_template_get (&sink_factory)); | ||
90 | llgst_element_class_set_details (element_class, &element_details); | ||
91 | } | ||
92 | |||
93 | |||
94 | static void | ||
95 | gst_slvideo_finalize (GObject * object) | ||
96 | { | ||
97 | GstSLVideo *slvideo; | ||
98 | slvideo = GST_SLVIDEO (object); | ||
99 | if (slvideo->caps) | ||
100 | { | ||
101 | llgst_caps_unref(slvideo->caps); | ||
102 | } | ||
103 | |||
104 | G_OBJECT_CLASS(parent_class)->finalize (object); | ||
105 | } | ||
106 | |||
107 | |||
108 | static GstFlowReturn | ||
109 | gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf) | ||
110 | { | ||
111 | GstSLVideo *slvideo; | ||
112 | llg_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); | ||
113 | |||
114 | slvideo = GST_SLVIDEO(bsink); | ||
115 | |||
116 | #if 0 | ||
117 | fprintf(stderr, "\n\ntransferring a frame of %dx%d <- %p (%d)\n\n", | ||
118 | slvideo->width, slvideo->height, GST_BUFFER_DATA(buf), | ||
119 | slvideo->format); | ||
120 | #endif | ||
121 | if (GST_BUFFER_DATA(buf)) | ||
122 | { | ||
123 | // copy frame and frame info into neutral territory | ||
124 | GST_OBJECT_LOCK(slvideo); | ||
125 | slvideo->retained_frame_ready = TRUE; | ||
126 | slvideo->retained_frame_width = slvideo->width; | ||
127 | slvideo->retained_frame_height = slvideo->height; | ||
128 | slvideo->retained_frame_format = slvideo->format; | ||
129 | int rowbytes = | ||
130 | SLVPixelFormatBytes[slvideo->retained_frame_format] * | ||
131 | slvideo->retained_frame_width; | ||
132 | int needbytes = rowbytes * slvideo->retained_frame_width; | ||
133 | // resize retained frame hunk only if necessary | ||
134 | if (needbytes != slvideo->retained_frame_allocbytes) | ||
135 | { | ||
136 | delete[] slvideo->retained_frame_data; | ||
137 | slvideo->retained_frame_data = new U8[needbytes]; | ||
138 | slvideo->retained_frame_allocbytes = needbytes; | ||
139 | |||
140 | } | ||
141 | // copy the actual frame data to neutral territory - | ||
142 | // flipped, for GL reasons | ||
143 | for (int ypos=0; ypos<slvideo->height; ++ypos) | ||
144 | { | ||
145 | memcpy(&slvideo->retained_frame_data[(slvideo->height-1-ypos)*rowbytes], | ||
146 | &(((U8*)GST_BUFFER_DATA(buf))[ypos*rowbytes]), | ||
147 | rowbytes); | ||
148 | } | ||
149 | // done with the shared data | ||
150 | GST_OBJECT_UNLOCK(slvideo); | ||
151 | } | ||
152 | |||
153 | return GST_FLOW_OK; | ||
154 | } | ||
155 | |||
156 | |||
157 | static GstStateChangeReturn | ||
158 | gst_slvideo_change_state(GstElement * element, GstStateChange transition) | ||
159 | { | ||
160 | GstSLVideo *slvideo; | ||
161 | GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; | ||
162 | |||
163 | slvideo = GST_SLVIDEO (element); | ||
164 | |||
165 | switch (transition) { | ||
166 | case GST_STATE_CHANGE_NULL_TO_READY: | ||
167 | break; | ||
168 | case GST_STATE_CHANGE_READY_TO_PAUSED: | ||
169 | break; | ||
170 | case GST_STATE_CHANGE_PAUSED_TO_PLAYING: | ||
171 | break; | ||
172 | default: | ||
173 | break; | ||
174 | } | ||
175 | |||
176 | ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); | ||
177 | if (ret == GST_STATE_CHANGE_FAILURE) | ||
178 | return ret; | ||
179 | |||
180 | switch (transition) { | ||
181 | case GST_STATE_CHANGE_PLAYING_TO_PAUSED: | ||
182 | break; | ||
183 | case GST_STATE_CHANGE_PAUSED_TO_READY: | ||
184 | slvideo->fps_n = 0; | ||
185 | slvideo->fps_d = 1; | ||
186 | GST_VIDEO_SINK_WIDTH(slvideo) = 0; | ||
187 | GST_VIDEO_SINK_HEIGHT(slvideo) = 0; | ||
188 | break; | ||
189 | case GST_STATE_CHANGE_READY_TO_NULL: | ||
190 | break; | ||
191 | default: | ||
192 | break; | ||
193 | } | ||
194 | |||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | |||
199 | static GstCaps * | ||
200 | gst_slvideo_get_caps (GstBaseSink * bsink) | ||
201 | { | ||
202 | GstSLVideo *slvideo; | ||
203 | slvideo = GST_SLVIDEO(bsink); | ||
204 | |||
205 | return llgst_caps_ref (slvideo->caps); | ||
206 | } | ||
207 | |||
208 | |||
209 | /* this function handles the link with other elements */ | ||
210 | static gboolean | ||
211 | gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps) | ||
212 | { | ||
213 | GstSLVideo *filter; | ||
214 | GstStructure *structure; | ||
215 | GstCaps *intersection; | ||
216 | |||
217 | GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps); | ||
218 | |||
219 | filter = GST_SLVIDEO(bsink); | ||
220 | |||
221 | intersection = llgst_caps_intersect (filter->caps, caps); | ||
222 | if (llgst_caps_is_empty (intersection)) | ||
223 | { | ||
224 | // no overlap between our caps and requested caps | ||
225 | return FALSE; | ||
226 | } | ||
227 | llgst_caps_unref(intersection); | ||
228 | |||
229 | int width, height; | ||
230 | gboolean ret; | ||
231 | const GValue *fps; | ||
232 | const GValue *par; | ||
233 | structure = llgst_caps_get_structure (caps, 0); | ||
234 | ret = llgst_structure_get_int (structure, "width", &width); | ||
235 | ret = ret && llgst_structure_get_int (structure, "height", &height); | ||
236 | fps = llgst_structure_get_value (structure, "framerate"); | ||
237 | ret = ret && (fps != NULL); | ||
238 | par = llgst_structure_get_value (structure, "pixel-aspect-ratio"); | ||
239 | if (!ret) | ||
240 | return FALSE; | ||
241 | |||
242 | filter->width = width; | ||
243 | filter->height = height; | ||
244 | filter->fps_n = llgst_value_get_fraction_numerator(fps); | ||
245 | filter->fps_d = llgst_value_get_fraction_denominator(fps); | ||
246 | if (par) | ||
247 | { | ||
248 | filter->par_n = llgst_value_get_fraction_numerator(par); | ||
249 | filter->par_d = llgst_value_get_fraction_denominator(par); | ||
250 | } | ||
251 | else | ||
252 | { | ||
253 | filter->par_n = 1; | ||
254 | filter->par_d = 1; | ||
255 | } | ||
256 | GST_VIDEO_SINK_WIDTH(filter) = width; | ||
257 | GST_VIDEO_SINK_HEIGHT(filter) = height; | ||
258 | |||
259 | filter->format = SLV_PF_UNKNOWN; | ||
260 | if (0 == strcmp(llgst_structure_get_name(structure), | ||
261 | "video/x-raw-rgb")) | ||
262 | { | ||
263 | int red_mask; | ||
264 | int green_mask; | ||
265 | int blue_mask; | ||
266 | llgst_structure_get_int(structure, "red_mask", &red_mask); | ||
267 | llgst_structure_get_int(structure, "green_mask", &green_mask); | ||
268 | llgst_structure_get_int(structure, "blue_mask", &blue_mask); | ||
269 | if ((unsigned int)red_mask == 0xFF000000 && | ||
270 | (unsigned int)green_mask == 0x00FF0000 && | ||
271 | (unsigned int)blue_mask == 0x0000FF00) | ||
272 | { | ||
273 | filter->format = SLV_PF_RGBX; | ||
274 | //fprintf(stderr, "\n\nPIXEL FORMAT RGB\n\n"); | ||
275 | } else if ((unsigned int)red_mask == 0x0000FF00 && | ||
276 | (unsigned int)green_mask == 0x00FF0000 && | ||
277 | (unsigned int)blue_mask == 0xFF000000) | ||
278 | { | ||
279 | filter->format = SLV_PF_BGRX; | ||
280 | //fprintf(stderr, "\n\nPIXEL FORMAT BGR\n\n"); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | return TRUE; | ||
285 | } | ||
286 | |||
287 | |||
288 | static gboolean | ||
289 | gst_slvideo_start (GstBaseSink * bsink) | ||
290 | { | ||
291 | GstSLVideo *slvideo; | ||
292 | gboolean ret = TRUE; | ||
293 | |||
294 | slvideo = GST_SLVIDEO(bsink); | ||
295 | |||
296 | return ret; | ||
297 | } | ||
298 | |||
299 | static gboolean | ||
300 | gst_slvideo_stop (GstBaseSink * bsink) | ||
301 | { | ||
302 | GstSLVideo *slvideo; | ||
303 | slvideo = GST_SLVIDEO(bsink); | ||
304 | |||
305 | // free-up retained frame buffer | ||
306 | GST_OBJECT_LOCK(slvideo); | ||
307 | slvideo->retained_frame_ready = FALSE; | ||
308 | delete[] slvideo->retained_frame_data; | ||
309 | slvideo->retained_frame_data = NULL; | ||
310 | slvideo->retained_frame_allocbytes = 0; | ||
311 | GST_OBJECT_UNLOCK(slvideo); | ||
312 | |||
313 | return TRUE; | ||
314 | } | ||
315 | |||
316 | |||
317 | static gboolean | ||
318 | gst_slvideo_unlock (GstBaseSink * bsink) | ||
319 | { | ||
320 | // nothing really to do here. | ||
321 | return TRUE; | ||
322 | } | ||
323 | |||
324 | |||
325 | /* initialize the plugin's class */ | ||
326 | static void | ||
327 | gst_slvideo_class_init (GstSLVideoClass * klass) | ||
328 | { | ||
329 | GObjectClass *gobject_class; | ||
330 | GstElementClass *gstelement_class; | ||
331 | GstBaseSinkClass *gstbasesink_class; | ||
332 | |||
333 | gobject_class = (GObjectClass *) klass; | ||
334 | gstelement_class = (GstElementClass *) klass; | ||
335 | gstbasesink_class = (GstBaseSinkClass *) klass; | ||
336 | |||
337 | gobject_class->finalize = gst_slvideo_finalize; | ||
338 | gobject_class->set_property = gst_slvideo_set_property; | ||
339 | gobject_class->get_property = gst_slvideo_get_property; | ||
340 | |||
341 | gstelement_class->change_state = gst_slvideo_change_state; | ||
342 | |||
343 | gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_slvideo_get_caps); | ||
344 | gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR( gst_slvideo_set_caps); | ||
345 | //gstbasesink_class->buffer_alloc=GST_DEBUG_FUNCPTR(gst_slvideo_buffer_alloc); | ||
346 | //gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_slvideo_get_times); | ||
347 | gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_slvideo_show_frame); | ||
348 | gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_slvideo_show_frame); | ||
349 | |||
350 | gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_slvideo_start); | ||
351 | gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_slvideo_stop); | ||
352 | |||
353 | gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_slvideo_unlock); | ||
354 | } | ||
355 | |||
356 | |||
357 | static void | ||
358 | gst_slvideo_update_caps (GstSLVideo * slvideo) | ||
359 | { | ||
360 | GstCaps *caps; | ||
361 | |||
362 | // GStreamer will automatically convert colourspace if necessary. | ||
363 | // GStreamer will automatically resize media to one of these enumerated | ||
364 | // powers-of-two that we ask for (yay GStreamer!) | ||
365 | caps = llgst_caps_from_string (SLV_ALLCAPS); | ||
366 | |||
367 | llgst_caps_replace (&slvideo->caps, caps); | ||
368 | } | ||
369 | |||
370 | |||
371 | /* initialize the new element | ||
372 | * instantiate pads and add them to element | ||
373 | * set functions | ||
374 | * initialize structure | ||
375 | */ | ||
376 | static void | ||
377 | gst_slvideo_init (GstSLVideo * filter, | ||
378 | GstSLVideoClass * gclass) | ||
379 | { | ||
380 | filter->width = -1; | ||
381 | filter->height = -1; | ||
382 | |||
383 | // this is the info we share with the client app | ||
384 | GST_OBJECT_LOCK(filter); | ||
385 | filter->retained_frame_ready = FALSE; | ||
386 | filter->retained_frame_data = NULL; | ||
387 | filter->retained_frame_allocbytes = 0; | ||
388 | filter->retained_frame_width = filter->width; | ||
389 | filter->retained_frame_height = filter->height; | ||
390 | filter->retained_frame_format = SLV_PF_UNKNOWN; | ||
391 | GST_OBJECT_UNLOCK(filter); | ||
392 | |||
393 | gst_slvideo_update_caps(filter); | ||
394 | } | ||
395 | |||
396 | static void | ||
397 | gst_slvideo_set_property (GObject * object, guint prop_id, | ||
398 | const GValue * value, GParamSpec * pspec) | ||
399 | { | ||
400 | llg_return_if_fail (GST_IS_SLVIDEO (object)); | ||
401 | |||
402 | switch (prop_id) { | ||
403 | default: | ||
404 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||
405 | break; | ||
406 | } | ||
407 | } | ||
408 | |||
409 | static void | ||
410 | gst_slvideo_get_property (GObject * object, guint prop_id, | ||
411 | GValue * value, GParamSpec * pspec) | ||
412 | { | ||
413 | llg_return_if_fail (GST_IS_SLVIDEO (object)); | ||
414 | |||
415 | switch (prop_id) { | ||
416 | default: | ||
417 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||
418 | break; | ||
419 | } | ||
420 | } | ||
421 | |||
422 | |||
423 | /* entry point to initialize the plug-in | ||
424 | * initialize the plug-in itself | ||
425 | * register the element factories and pad templates | ||
426 | * register the features | ||
427 | */ | ||
428 | static gboolean | ||
429 | plugin_init (GstPlugin * plugin) | ||
430 | { | ||
431 | //fprintf(stderr, "\n\n\nPLUGIN INIT\n\n\n"); | ||
432 | |||
433 | GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, "private-slvideo-plugin", | ||
434 | 0, "Second Life Video Sink"); | ||
435 | |||
436 | return llgst_element_register (plugin, "private-slvideo", | ||
437 | GST_RANK_NONE, GST_TYPE_SLVIDEO); | ||
438 | } | ||
439 | |||
440 | /* this is the structure that gstreamer looks for to register plugins | ||
441 | */ | ||
442 | /* NOTE: Can't rely upon GST_PLUGIN_DEFINE_STATIC to self-register, since | ||
443 | some g++ versions buggily avoid __attribute__((constructor)) functions - | ||
444 | so we provide an explicit plugin init function. | ||
445 | */ | ||
446 | void gst_slvideo_init_class (void) | ||
447 | { | ||
448 | #define PACKAGE "packagehack" | ||
449 | static GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, | ||
450 | GST_VERSION_MINOR, | ||
451 | "private-slvideoplugin", | ||
452 | "SL Video sink plugin", | ||
453 | plugin_init, "0.1", GST_LICENSE_UNKNOWN, | ||
454 | "Second Life", | ||
455 | "http://www.secondlife.com/"); | ||
456 | #undef PACKAGE | ||
457 | ll_gst_plugin_register_static (&gst_plugin_desc); | ||
458 | //fprintf(stderr, "\n\n\nCLASS INIT\n\n\n"); | ||
459 | } | ||
460 | |||
461 | #endif // LL_GSTREAMER_ENABLED | ||
diff --git a/linden/indra/llmedia/llmediaimplgstreamervidplug.h b/linden/indra/llmedia/llmediaimplgstreamervidplug.h new file mode 100644 index 0000000..2bfb853 --- /dev/null +++ b/linden/indra/llmedia/llmediaimplgstreamervidplug.h | |||
@@ -0,0 +1,101 @@ | |||
1 | /** | ||
2 | * @file llmediaimplgstreamervidplug.h | ||
3 | * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl | ||
4 | * | ||
5 | * Copyright (c) 2007-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * Second Life Viewer Source Code | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | #ifndef __GST_SLVIDEO_H__ | ||
30 | #define __GST_SLVIDEO_H__ | ||
31 | |||
32 | #if LL_GSTREAMER_ENABLED | ||
33 | |||
34 | extern "C" { | ||
35 | #include <gst/gst.h> | ||
36 | #include <gst/video/video.h> | ||
37 | #include <gst/video/gstvideosink.h> | ||
38 | } | ||
39 | |||
40 | G_BEGIN_DECLS | ||
41 | |||
42 | /* #defines don't like whitespacey bits */ | ||
43 | #define GST_TYPE_SLVIDEO \ | ||
44 | (gst_slvideo_get_type()) | ||
45 | #define GST_SLVIDEO(obj) \ | ||
46 | (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SLVIDEO,GstSLVideo)) | ||
47 | #define GST_SLVIDEO_CLASS(klass) \ | ||
48 | (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SLVIDEO,GstSLVideoClass)) | ||
49 | #define GST_IS_SLVIDEO(obj) \ | ||
50 | (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SLVIDEO)) | ||
51 | #define GST_IS_SLVIDEO_CLASS(klass) \ | ||
52 | (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SLVIDEO)) | ||
53 | |||
54 | typedef struct _GstSLVideo GstSLVideo; | ||
55 | typedef struct _GstSLVideoClass GstSLVideoClass; | ||
56 | |||
57 | typedef enum { | ||
58 | SLV_PF_UNKNOWN = 0, | ||
59 | SLV_PF_RGBX = 1, | ||
60 | SLV_PF_BGRX = 2, | ||
61 | SLV__END = 3 | ||
62 | } SLVPixelFormat; | ||
63 | const int SLVPixelFormatBytes[SLV__END] = {1, 4, 4}; | ||
64 | |||
65 | struct _GstSLVideo | ||
66 | { | ||
67 | GstVideoSink video_sink; | ||
68 | |||
69 | GstCaps *caps; | ||
70 | |||
71 | int fps_n, fps_d; | ||
72 | int par_n, par_d; | ||
73 | int height, width; | ||
74 | SLVPixelFormat format; | ||
75 | |||
76 | // SHARED WITH APPLICATION: | ||
77 | // Access to the following should be protected by GST_OBJECT_LOCK() on | ||
78 | // the GstSLVideo object, and should be totally consistent upon UNLOCK | ||
79 | // (i.e. all written at once to reflect the current retained frame info | ||
80 | // when the retained frame is updated.) | ||
81 | bool retained_frame_ready; // new frame ready since flag last reset. (*TODO: could get the writer to wait on a semaphore instead of having the reader poll, potentially making dropped frames somewhat cheaper.) | ||
82 | U8* retained_frame_data; | ||
83 | int retained_frame_allocbytes; | ||
84 | int retained_frame_width, retained_frame_height; | ||
85 | SLVPixelFormat retained_frame_format; | ||
86 | }; | ||
87 | |||
88 | struct _GstSLVideoClass | ||
89 | { | ||
90 | GstVideoSink parent_class; | ||
91 | }; | ||
92 | |||
93 | GType gst_slvideo_get_type (void); | ||
94 | |||
95 | void gst_slvideo_init_class (void); | ||
96 | |||
97 | G_END_DECLS | ||
98 | |||
99 | #endif // LL_GSTREAMER_ENABLED | ||
100 | |||
101 | #endif /* __GST_SLVIDEO_H__ */ | ||
diff --git a/linden/indra/llmedia/llmediamoviebase.cpp b/linden/indra/llmedia/llmediamoviebase.cpp index 46b76b0..de9933b 100644 --- a/linden/indra/llmedia/llmediamoviebase.cpp +++ b/linden/indra/llmedia/llmediamoviebase.cpp | |||
@@ -30,6 +30,7 @@ | |||
30 | 30 | ||
31 | #include "llmediamoviebase.h" | 31 | #include "llmediamoviebase.h" |
32 | #include "llmediaimplquicktime.h" | 32 | #include "llmediaimplquicktime.h" |
33 | #include "llmediaimplgstreamer.h" | ||
33 | 34 | ||
34 | LLMediaMovieBase::LLMediaMovieBase() | 35 | LLMediaMovieBase::LLMediaMovieBase() |
35 | { | 36 | { |
@@ -47,6 +48,13 @@ LLMediaMovieBase* LLMediaMovieBase::make( const MediaType mediaTypeIn, S32 width | |||
47 | } | 48 | } |
48 | else | 49 | else |
49 | #endif | 50 | #endif |
51 | #if LL_GSTREAMER_ENABLED | ||
52 | if ( mediaTypeIn == QuickTime ) | ||
53 | { | ||
54 | return new LLMediaImplGStreamer (); | ||
55 | } | ||
56 | else | ||
57 | #endif | ||
50 | 58 | ||
51 | return 0; | 59 | return 0; |
52 | } | 60 | } |