Mercurial > mplayer.hg
annotate stream/tvi_dshow.c @ 27409:e2de11109139
If (has outline) blur(outline) else blur(glyph).
If there is an outline, the glyph itself should not be blurred. Keeps
the border between glyph and outline clear (unblurred), which is
probably how it should be.
Patch by Diogo Franco (diogomfranco gmail com).
author | eugeni |
---|---|
date | Thu, 07 Aug 2008 22:20:58 +0000 |
parents | 14c5017f40d2 |
children | 1779bbc0733a |
rev | line source |
---|---|
24744 | 1 /* |
26737
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
2 * TV support under Win32 |
24744 | 3 * |
26737
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
4 * (C) 2007 Vladimir Voroshilov <voroshil@gmail.com> |
24744 | 5 * |
26737
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
6 * Based on tvi_dummy.c with help of tv.c, tvi_v4l2.c code. |
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
7 * |
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
8 * This file is part of MPlayer. |
24744 | 9 * |
26737
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
10 * MPlayer is free software; you can redistribute it and/or modify |
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
11 * it under the terms of the GNU General Public License as published by |
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
12 * the Free Software Foundation; either version 2 of the License, or |
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
13 * (at your option) any later version. |
24744 | 14 * |
26737
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
15 * MPlayer is distributed in the hope that it will be useful, |
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
18 * GNU General Public License for more details. |
24744 | 19 * |
26737
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
20 * You should have received a copy of the GNU General Public License along |
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
21 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
23 */ |
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
24 |
a26e50cae389
Use standard license headers with standard formatting.
diego
parents:
25689
diff
changeset
|
25 /* |
24744 | 26 * WARNING: This is alpha code! |
27 * | |
28 * Abilities: | |
29 * * Watching TV under Win32 using WDM Capture driver and DirectShow | |
30 * * Grabbing synchronized audio/video with mencoder (synchronization is beeing done by DirectShow) | |
31 * * If device driver provides IAMStreamConfig interface, user can choose width/height with "-tv height=<h>:width=<w>" | |
32 * * Adjusting BRIGHTNESS,HUE,SATURATION,CONTRAST if supported by device | |
33 * * Selecting Tuner,S-Video,... as media source | |
34 * * User can select used video capture device, passing -tv device=<dev#> | |
35 * * User can select used audio input, passing -tv audioid=<input#> | |
36 * | |
37 * options which will not be implemented (probably sometime in future, if possible): | |
38 * * alsa | |
39 * * mjpeg | |
40 * * decimation=<1|2|4> | |
41 * * quality=<0\-100> | |
42 * * forceaudio | |
43 * * forcechan=<1\-2> | |
44 * * [volume|bass|treble|balance] | |
45 * | |
46 * Works with: | |
47 * - LifeView FlyTV Prime 34FM (SAA7134 based) with driver from Ivan Uskov | |
48 * Partially works with: | |
49 * - ATI 9200 VIVO based card | |
50 * - ATI AIW 7500 | |
51 * - nVidia Ti-4400 | |
52 * | |
53 * Known bugs: | |
54 * * stream goes with 24.93 FPS (NTSC), while reporting 25 FPS (PAL) ?! | |
55 * * direct set frequency call does not work ('Insufficient Buffer' error) | |
56 * * audio stream goes with about 1 sample/sec rate when capturing sound from audio card | |
57 * | |
58 * TODO: | |
59 * * check audio with small buffer on vivo !!! | |
60 * * norm for IAMVideoDecoder and for IAMTVtuner - differs !! | |
61 * * check how to change TVFormat on VIVO card without tuner | |
62 * * Flip image upside-down for RGB formats. | |
63 * * | |
64 * * remove debug sleep() | |
65 * * Add some notes to methods' parameters | |
66 * * refactor console messages | |
67 * * check using header files and keep only needed | |
68 * * add additional comments to methods' bodies | |
69 * | |
70 */ | |
71 | |
72 | |
73 /// \ingroup tvi_dshow | |
74 | |
75 #include "config.h" | |
76 | |
77 #include <stdio.h> | |
78 #include "libmpcodecs/img_format.h" | |
79 #include "libaf/af_format.h" | |
80 #include "help_mp.h" | |
81 #include "osdep/timer.h" | |
82 | |
83 | |
84 #include "tv.h" | |
85 #include "mp_msg.h" | |
86 #include "frequencies.h" | |
87 | |
88 | |
89 #include "tvi_dshow.h" | |
90 | |
91 static tvi_handle_t *tvi_init_dshow(tv_param_t* tv_param); | |
92 | |
93 /* | |
94 *--------------------------------------------------------------------------------------- | |
95 * | |
96 * Data structures | |
97 * | |
98 *--------------------------------------------------------------------------------------- | |
99 */ | |
100 /** | |
101 information about this file | |
102 */ | |
25689 | 103 const tvi_info_t tvi_info_dshow = { |
24744 | 104 tvi_init_dshow, |
105 "DirectShow TV", | |
106 "dshow", | |
107 "Vladimir Voroshilov", | |
108 "Very experimental!! Use with caution" | |
109 }; | |
110 | |
111 | |
112 /** | |
113 ringbuffer related info | |
114 */ | |
115 typedef struct { | |
116 CRITICAL_SECTION *pMutex; ///< pointer to critical section (mutex) | |
117 char **ringbuffer; ///< ringbuffer array | |
118 double*dpts; ///< samples' timestamps | |
119 | |
120 int buffersize; ///< size of buffer in blocks | |
121 int blocksize; ///< size of individual block | |
122 int head; ///< index of first valid sample | |
123 int tail; ///< index of last valid sample | |
124 int count; ///< count of valid samples in ringbuffer | |
125 double tStart; ///< pts of first sample (first sample should have pts 0) | |
126 } grabber_ringbuffer_t; | |
127 | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
128 typedef enum { unknown, video, audio, vbi } stream_type; |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
129 |
24744 | 130 /** |
131 CSampleGrabberCD definition | |
132 */ | |
133 typedef struct CSampleGrabberCB { | |
134 ISampleGrabberCBVtbl *lpVtbl; | |
135 int refcount; | |
136 GUID interfaces[2]; | |
137 grabber_ringbuffer_t *pbuf; | |
138 } CSampleGrabberCB; | |
139 | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
140 /** |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
141 Chain related structure |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
142 */ |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
143 typedef struct { |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
144 stream_type type; ///< stream type |
25080 | 145 const GUID* majortype; ///< GUID of major mediatype (video/audio/vbi) |
25094
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
146 const GUID* pin_category; ///< pin category (pointer to one of PIN_CATEGORY_*) |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
147 |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
148 IBaseFilter *pCaptureFilter; ///< capture device filter |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
149 IAMStreamConfig *pStreamConfig; ///< for configuring stream |
25087
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
150 ISampleGrabber *pSG; ///< ISampleGrabber interface of SampleGrabber filter |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
151 IBaseFilter *pSGF; ///< IBaseFilter interface of SampleGrabber filter |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
152 IPin *pCapturePin; ///< output capture pin |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
153 IPin *pSGIn; ///< input pin of SampleGrabber filter |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
154 |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
155 grabber_ringbuffer_t *rbuf; ///< sample frabber data |
25086
e91503fbf524
Move pointer to SampleGrabber filter into chain structure.
voroshil
parents:
25085
diff
changeset
|
156 CSampleGrabberCB* pCSGCB; ///< callback object |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
157 |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
158 AM_MEDIA_TYPE *pmt; ///< stream properties. |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
159 int nFormatUsed; ///< index of used format |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
160 AM_MEDIA_TYPE **arpmt; ///< available formats |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
161 void** arStreamCaps; ///< VIDEO_STREAM_CONFIG_CAPS or AUDIO_STREAM_CONFIG_CAPS |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
162 } chain_t; |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
163 |
24744 | 164 typedef struct { |
165 int dev_index; ///< capture device index in device list (defaul: 0, first available device) | |
166 int adev_index; ///< audio capture device index in device list (default: -1, not used) | |
167 int immediate_mode; ///< immediate mode (no sound capture) | |
168 int state; ///< state: 1-filter graph running, 0-filter graph stopped | |
169 int direct_setfreq_call; ///< 0-find nearest channels from system channel list(workaround),1-direct call to set frequency | |
170 int direct_getfreq_call; ///< 0-find frequncy from frequency table (workaround),1-direct call to get frequency | |
171 | |
172 int fcc; ///< used video format code (FourCC) | |
173 int width; ///< picture width (default: auto) | |
174 int height; ///< picture height (default: auto) | |
175 | |
176 int channels; ///< number of audio channels (default: auto) | |
177 int samplerate; ///< audio samplerate (default: auto) | |
178 | |
179 long *freq_table; ///< frequency table (in Hz) | |
180 int freq_table_len; ///< length of freq table | |
181 int first_channel; ///< channel number of first entry in freq table | |
182 int input; ///< used input | |
183 | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
184 chain_t* chains[3]; ///< chains' data (0-video, 1-audio, 2-vbi) |
24744 | 185 |
186 IAMTVTuner *pTVTuner; ///< interface for tuner device | |
187 IGraphBuilder *pGraph; ///< filter graph | |
188 ICaptureGraphBuilder2 *pBuilder; ///< graph builder | |
189 IMediaControl *pMediaControl; ///< interface for controlling graph (start, stop,...) | |
190 IAMVideoProcAmp *pVideoProcAmp; ///< for adjusting hue,saturation,etc | |
191 IAMCrossbar *pCrossbar; ///< for selecting input (Tuner,Composite,S-Video,...) | |
192 DWORD dwRegister; ///< allow graphedit to connect to our graph | |
193 void *priv_vbi; ///< private VBI data structure | |
194 tt_stream_props tsp; ///< data for VBI initialization | |
195 | |
196 tv_param_t* tv_param; ///< TV parameters | |
197 } priv_t; | |
198 | |
199 #include "tvi_def.h" | |
200 | |
201 /** | |
202 country table entry structure (for loading freq table stored in kstvtuner.ax | |
203 | |
204 \note | |
205 structure have to be 2-byte aligned and have 10-byte length!! | |
206 */ | |
207 typedef struct __attribute__((__packed__)) { | |
208 WORD CountryCode; ///< Country code | |
209 WORD CableFreqTable; ///< index of resource with frequencies for cable channels | |
210 WORD BroadcastFreqTable; ///< index of resource with frequencies for broadcast channels | |
211 DWORD VideoStandard; ///< used video standard | |
212 } TRCCountryList; | |
213 /** | |
214 information about image formats | |
215 */ | |
216 typedef struct { | |
217 uint32_t fmt; ///< FourCC | |
218 const GUID *subtype; ///< DirectShow's subtype | |
219 int nBits; ///< number of bits | |
220 int nCompression; ///< complression | |
221 int tail; ///< number of additional bytes followed VIDEOINFOHEADER structure | |
222 } img_fmt; | |
223 | |
224 /* | |
225 *--------------------------------------------------------------------------------------- | |
226 * | |
227 * Methods forward declaration | |
228 * | |
229 *--------------------------------------------------------------------------------------- | |
230 */ | |
231 static HRESULT init_ringbuffer(grabber_ringbuffer_t * rb, int buffersize, | |
232 int blocksize); | |
233 static HRESULT show_filter_info(IBaseFilter * pFilter); | |
234 #if 0 | |
235 //defined in current MinGW release | |
236 HRESULT STDCALL GetRunningObjectTable(DWORD, IRunningObjectTable **); | |
237 HRESULT STDCALL CreateItemMoniker(LPCOLESTR, LPCOLESTR, IMoniker **); | |
238 #endif | |
239 static CSampleGrabberCB *CSampleGrabberCB_Create(grabber_ringbuffer_t * | |
240 pbuf); | |
241 static int set_crossbar_input(priv_t * priv, int input); | |
242 static int subtype2imgfmt(const GUID * subtype); | |
243 | |
244 /* | |
245 *--------------------------------------------------------------------------------------- | |
246 * | |
247 * Global constants and variables | |
248 * | |
249 *--------------------------------------------------------------------------------------- | |
250 */ | |
251 /** | |
252 lookup tables for physical connector types | |
253 */ | |
254 static const struct { | |
255 long type; | |
256 char *name; | |
257 } tv_physcon_types[]={ | |
258 {PhysConn_Video_Tuner, "Tuner" }, | |
259 {PhysConn_Video_Composite, "Composite" }, | |
260 {PhysConn_Video_SVideo, "S-Video" }, | |
261 {PhysConn_Video_RGB, "RGB" }, | |
262 {PhysConn_Video_YRYBY, "YRYBY" }, | |
263 {PhysConn_Video_SerialDigital, "SerialDigital" }, | |
264 {PhysConn_Video_ParallelDigital, "ParallelDigital"}, | |
265 {PhysConn_Video_VideoDecoder, "VideoDecoder" }, | |
266 {PhysConn_Video_VideoEncoder, "VideoEncoder" }, | |
267 {PhysConn_Video_SCART, "SCART" }, | |
268 {PhysConn_Video_Black, "Blaack" }, | |
269 {PhysConn_Audio_Tuner, "Tuner" }, | |
270 {PhysConn_Audio_Line, "Line" }, | |
271 {PhysConn_Audio_Mic, "Mic" }, | |
272 {PhysConn_Audio_AESDigital, "AESDiital" }, | |
273 {PhysConn_Audio_SPDIFDigital, "SPDIFDigital" }, | |
274 {PhysConn_Audio_AudioDecoder, "AudioDecoder" }, | |
275 {PhysConn_Audio_SCSI, "SCSI" }, | |
276 {PhysConn_Video_SCSI, "SCSI" }, | |
277 {PhysConn_Audio_AUX, "AUX" }, | |
278 {PhysConn_Video_AUX, "AUX" }, | |
279 {PhysConn_Audio_1394, "1394" }, | |
280 {PhysConn_Video_1394, "1394" }, | |
281 {PhysConn_Audio_USB, "USB" }, | |
282 {PhysConn_Video_USB, "USB" }, | |
283 {-1, NULL } | |
284 }; | |
285 | |
286 static const struct { | |
287 char *chanlist_name; | |
288 int country_code; | |
289 } tv_chanlist2country[]={ | |
290 {"us-bcast", 1}, | |
291 {"russia", 7}, | |
292 {"argentina", 54}, | |
293 {"japan-bcast", 81}, | |
294 {"china-bcast", 86}, | |
295 {"southafrica", 27}, | |
296 {"australia", 61}, | |
297 {"ireland", 353}, | |
298 {"france", 33}, | |
299 {"italy", 39}, | |
300 {"newzealand", 64}, | |
301 //directshow table uses eastern europe freq table for russia | |
302 {"europe-east", 7}, | |
303 //directshow table uses western europe freq table for germany | |
304 {"europe-west", 49}, | |
305 /* cable channels */ | |
306 {"us-cable", 1}, | |
307 {"us-cable-hrc", 1}, | |
308 {"japan-cable", 81}, | |
309 //default is USA | |
310 {NULL, 1} | |
311 }; | |
312 | |
313 /** | |
314 array, contains information about various supported (i hope) image formats | |
315 */ | |
316 static const img_fmt img_fmt_list[] = { | |
25054 | 317 {IMGFMT_YUY2, &MEDIASUBTYPE_YUY2, 16, IMGFMT_YUY2, 0}, |
318 {IMGFMT_YV12, &MEDIASUBTYPE_YV12, 12, IMGFMT_YV12, 0}, | |
319 {IMGFMT_IYUV, &MEDIASUBTYPE_IYUV, 12, IMGFMT_IYUV, 0}, | |
320 {IMGFMT_I420, &MEDIASUBTYPE_I420, 12, IMGFMT_I420, 0}, | |
321 {IMGFMT_UYVY, &MEDIASUBTYPE_UYVY, 16, IMGFMT_UYVY, 0}, | |
322 {IMGFMT_YVYU, &MEDIASUBTYPE_YVYU, 16, IMGFMT_YVYU, 0}, | |
323 {IMGFMT_YVU9, &MEDIASUBTYPE_YVU9, 9, IMGFMT_YVU9, 0}, | |
324 {IMGFMT_BGR32, &MEDIASUBTYPE_RGB32, 32, 0, 0}, | |
325 {IMGFMT_BGR24, &MEDIASUBTYPE_RGB24, 24, 0, 0}, | |
326 {IMGFMT_BGR16, &MEDIASUBTYPE_RGB565, 16, 3, 12}, | |
327 {IMGFMT_BGR15, &MEDIASUBTYPE_RGB555, 16, 3, 12}, | |
328 {0, &GUID_NULL, 0, 0, 0} | |
24744 | 329 }; |
330 | |
331 #define TV_NORMS_COUNT 19 | |
332 static const struct { | |
333 long index; | |
334 char *name; | |
335 } tv_norms[TV_NORMS_COUNT] = { | |
336 { | |
337 AnalogVideo_NTSC_M, "ntsc-m"}, { | |
338 AnalogVideo_NTSC_M_J, "ntsc-mj"}, { | |
339 AnalogVideo_NTSC_433, "ntsc-433"}, { | |
340 AnalogVideo_PAL_B, "pal-b"}, { | |
341 AnalogVideo_PAL_D, "pal-d"}, { | |
342 AnalogVideo_PAL_G, "pal-g"}, { | |
343 AnalogVideo_PAL_H, "pal-h"}, { | |
344 AnalogVideo_PAL_I, "pal-i"}, { | |
345 AnalogVideo_PAL_M, "pal-m"}, { | |
346 AnalogVideo_PAL_N, "pal-n"}, { | |
347 AnalogVideo_PAL_60, "pal-60"}, { | |
348 AnalogVideo_SECAM_B, "secam-b"}, { | |
349 AnalogVideo_SECAM_D, "secam-d"}, { | |
350 AnalogVideo_SECAM_G, "secam-g"}, { | |
351 AnalogVideo_SECAM_H, "secam-h"}, { | |
352 AnalogVideo_SECAM_K, "secam-k"}, { | |
353 AnalogVideo_SECAM_K1, "secam-k1"}, { | |
354 AnalogVideo_SECAM_L, "secam-l"}, { | |
355 AnalogVideo_SECAM_L1, "secam-l1"} | |
356 }; | |
357 static long tv_available_norms[TV_NORMS_COUNT]; | |
358 static int tv_available_norms_count = 0; | |
359 | |
360 | |
361 static long *tv_available_inputs; | |
362 static int tv_available_inputs_count = 0; | |
363 | |
364 /* | |
365 *--------------------------------------------------------------------------------------- | |
366 * | |
367 * Various GUID definitions | |
368 * | |
369 *--------------------------------------------------------------------------------------- | |
370 */ | |
371 /// CLSID definitions (used for CoCreateInstance call) | |
372 DEFINE_GUID(CLSID_SampleGrabber, 0xC1F400A0, 0x3F08, 0x11d3, 0x9F, 0x0B, | |
373 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37); | |
374 DEFINE_GUID(CLSID_NullRenderer, 0xC1F400A4, 0x3F08, 0x11d3, 0x9F, 0x0B, | |
375 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37); | |
376 DEFINE_GUID(CLSID_SystemDeviceEnum, 0x62BE5D10, 0x60EB, 0x11d0, 0xBD, 0x3B, | |
377 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86); | |
378 DEFINE_GUID(CLSID_CaptureGraphBuilder2, 0xBF87B6E1, 0x8C27, 0x11d0, 0xB3, | |
379 0xF0, 0x00, 0xAA, 0x00, 0x37, 0x61, 0xC5); | |
380 DEFINE_GUID(CLSID_VideoInputDeviceCategory, 0x860BB310, 0x5D01, 0x11d0, | |
381 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86); | |
382 DEFINE_GUID(CLSID_AudioInputDeviceCategory, 0x33d9a762, 0x90c8, 0x11d0, | |
383 0xbd, 0x43, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86); | |
384 DEFINE_GUID(CLSID_FilterGraph, 0xe436ebb3, 0x524f, 0x11ce, 0x9f, 0x53, | |
385 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70); | |
386 DEFINE_GUID(CLSID_SystemClock, 0xe436ebb1, 0x524f, 0x11ce, 0x9f, 0x53, | |
387 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70); | |
388 #ifdef NOT_USED | |
389 DEFINE_GUID(CLSID_CaptureGraphBuilder, 0xBF87B6E0, 0x8C27, 0x11d0, 0xB3, | |
390 0xF0, 0x00, 0xAA, 0x00, 0x37, 0x61, 0xC5); | |
391 DEFINE_GUID(CLSID_VideoPortManager, 0x6f26a6cd, 0x967b, 0x47fd, 0x87, 0x4a, | |
392 0x7a, 0xed, 0x2c, 0x9d, 0x25, 0xa2); | |
393 DEFINE_GUID(IID_IPin, 0x56a86891, 0x0ad4, 0x11ce, 0xb0, 0x3a, 0x00, 0x20, | |
394 0xaf, 0x0b, 0xa7, 0x70); | |
395 DEFINE_GUID(IID_ICaptureGraphBuilder, 0xbf87b6e0, 0x8c27, 0x11d0, 0xb3, | |
396 0xf0, 0x00, 0xaa, 0x00, 0x37, 0x61, 0xc5); | |
397 DEFINE_GUID(IID_IFilterGraph, 0x56a8689f, 0x0ad4, 0x11ce, 0xb0, 0x3a, 0x00, | |
398 0x20, 0xaf, 0x0b, 0xa7, 0x70); | |
399 DEFINE_GUID(PIN_CATEGORY_PREVIEW, 0xfb6c4282, 0x0353, 0x11d1, 0x90, 0x5f, | |
400 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba); | |
401 #endif | |
402 | |
403 /// IID definitions (used for QueryInterface call) | |
404 DEFINE_GUID(IID_IReferenceClock, 0x56a86897, 0x0ad4, 0x11ce, 0xb0, 0x3a, | |
405 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70); | |
406 DEFINE_GUID(IID_IAMBufferNegotiation, 0x56ED71A0, 0xAF5F, 0x11D0, 0xB3, 0xF0, | |
407 0x00, 0xAA, 0x00, 0x37, 0x61, 0xC5); | |
408 DEFINE_GUID(IID_IKsPropertySet, 0x31efac30, 0x515c, 0x11d0, 0xa9, 0xaa, | |
409 0x00, 0xaa, 0x00, 0x61, 0xbe, 0x93); | |
410 DEFINE_GUID(IID_ISampleGrabber, 0x6B652FFF, 0x11FE, 0x4fce, 0x92, 0xAD, | |
411 0x02, 0x66, 0xB5, 0xD7, 0xC7, 0x8F); | |
412 DEFINE_GUID(IID_ISampleGrabberCB, 0x0579154A, 0x2B53, 0x4994, 0xB0, 0xD0, | |
413 0xE7, 0x73, 0x14, 0x8E, 0xFF, 0x85); | |
414 DEFINE_GUID(IID_ICaptureGraphBuilder2, 0x93e5a4e0, 0x2d50, 0x11d2, 0xab, | |
415 0xfa, 0x00, 0xa0, 0xc9, 0xc6, 0xe3, 0x8d); | |
416 DEFINE_GUID(IID_ICreateDevEnum, 0x29840822, 0x5b84, 0x11d0, 0xbd, 0x3b, | |
417 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86); | |
418 DEFINE_GUID(IID_IGraphBuilder, 0x56a868a9, 0x0ad4, 0x11ce, 0xb0, 0x3a, | |
419 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70); | |
420 DEFINE_GUID(IID_IAMVideoProcAmp, 0xC6E13360, 0x30AC, 0x11d0, 0xA1, 0x8C, | |
421 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56); | |
422 DEFINE_GUID(IID_IVideoWindow, 0x56a868b4, 0x0ad4, 0x11ce, 0xb0, 0x3a, 0x00, | |
423 0x20, 0xaf, 0x0b, 0xa7, 0x70); | |
424 DEFINE_GUID(IID_IMediaControl, 0x56a868b1, 0x0ad4, 0x11ce, 0xb0, 0x3a, | |
425 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70); | |
426 DEFINE_GUID(IID_IAMTVTuner, 0x211A8766, 0x03AC, 0x11d1, 0x8D, 0x13, 0x00, | |
427 0xAA, 0x00, 0xBD, 0x83, 0x39); | |
428 DEFINE_GUID(IID_IAMCrossbar, 0xc6e13380, 0x30ac, 0x11d0, 0xa1, 0x8c, 0x00, | |
429 0xa0, 0xc9, 0x11, 0x89, 0x56); | |
430 DEFINE_GUID(IID_IAMStreamConfig, 0xc6e13340, 0x30ac, 0x11d0, 0xa1, 0x8c, | |
431 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56); | |
432 DEFINE_GUID(IID_IAMAudioInputMixer, 0x54C39221, 0x8380, 0x11d0, 0xB3, 0xF0, | |
433 0x00, 0xAA, 0x00, 0x37, 0x61, 0xC5); | |
434 DEFINE_GUID(IID_IAMTVAudio, 0x83EC1C30, 0x23D1, 0x11d1, 0x99, 0xE6, 0x00, | |
435 0xA0, 0xC9, 0x56, 0x02, 0x66); | |
436 DEFINE_GUID(IID_IAMAnalogVideoDecoder, 0xC6E13350, 0x30AC, 0x11d0, 0xA1, | |
437 0x8C, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56); | |
438 DEFINE_GUID(IID_IPropertyBag, 0x55272a00, 0x42cb, 0x11ce, 0x81, 0x35, 0x00, | |
439 0xaa, 0x00, 0x4b, 0xb8, 0x51); | |
440 DEFINE_GUID(PIN_CATEGORY_CAPTURE, 0xfb6c4281, 0x0353, 0x11d1, 0x90, 0x5f, | |
441 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba); | |
442 DEFINE_GUID(PIN_CATEGORY_VIDEOPORT, 0xfb6c4285, 0x0353, 0x11d1, 0x90, 0x5f, | |
443 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba); | |
444 DEFINE_GUID(PIN_CATEGORY_PREVIEW, 0xfb6c4282, 0x0353, 0x11d1, 0x90, 0x5f, | |
445 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba); | |
446 DEFINE_GUID(PIN_CATEGORY_VBI, 0xfb6c4284, 0x0353, 0x11d1, 0x90, 0x5f, | |
447 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba); | |
448 DEFINE_GUID(PROPSETID_TUNER, 0x6a2e0605, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, | |
449 0xa0, 0xc9, 0x11, 0x89, 0x56); | |
450 DEFINE_GUID(MEDIATYPE_VBI, 0xf72a76e1, 0xeb0a, 0x11d0, 0xac, 0xe4, 0x00, | |
451 0x00, 0xc0, 0xcc, 0x16, 0xba); | |
452 | |
453 #define INSTANCEDATA_OF_PROPERTY_PTR(x) (((KSPROPERTY*)(x)) + 1) | |
454 #define INSTANCEDATA_OF_PROPERTY_SIZE(x) (sizeof((x)) - sizeof(KSPROPERTY)) | |
455 | |
456 #define DEVICE_NAME_MAX_LEN 2000 | |
457 | |
458 /*--------------------------------------------------------------------------------------- | |
459 * Methods, called only from this file | |
460 *---------------------------------------------------------------------------------------*/ | |
461 | |
462 void set_buffer_preference(int nDiv,WAVEFORMATEX* pWF,IPin* pOutPin,IPin* pInPin){ | |
463 ALLOCATOR_PROPERTIES prop; | |
464 IAMBufferNegotiation* pBN; | |
465 HRESULT hr; | |
466 | |
467 prop.cbAlign = -1; | |
468 prop.cbBuffer = pWF->nAvgBytesPerSec/nDiv; | |
469 if (!prop.cbBuffer) | |
470 prop.cbBuffer = 1; | |
471 prop.cbBuffer += pWF->nBlockAlign - 1; | |
472 prop.cbBuffer -= prop.cbBuffer % pWF->nBlockAlign; | |
473 prop.cbPrefix = -1; | |
474 prop.cBuffers = -1; | |
475 | |
476 hr=OLE_QUERYINTERFACE(pOutPin,IID_IAMBufferNegotiation,pBN); | |
477 if(FAILED(hr)) | |
478 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: pOutPin->QueryInterface(IID_IAMBufferNegotiation) Error: 0x%x\n",(unsigned int)hr); | |
479 else{ | |
480 hr=OLE_CALL_ARGS(pBN,SuggestAllocatorProperties,&prop); | |
481 if(FAILED(hr)) | |
482 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow:pOutPin->SuggestAllocatorProperties Error:0x%x\n",(unsigned int)hr); | |
483 OLE_RELEASE_SAFE(pBN); | |
484 } | |
485 hr=OLE_QUERYINTERFACE(pInPin,IID_IAMBufferNegotiation,pBN); | |
486 if(FAILED(hr)) | |
487 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: pInPin->QueryInterface(IID_IAMBufferNegotiation) Error: 0x%x",(unsigned int)hr); | |
488 else{ | |
489 hr=OLE_CALL_ARGS(pBN,SuggestAllocatorProperties,&prop); | |
490 if(FAILED(hr)) | |
491 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: pInPit->SuggestAllocatorProperties Error:0x%x\n",(unsigned int)hr); | |
492 OLE_RELEASE_SAFE(pBN); | |
493 } | |
494 } | |
495 /* | |
496 *--------------------------------------------------------------------------------------- | |
497 * | |
498 * CSampleGrabberCD class. Used for receiving samples from DirectShow. | |
499 * | |
500 *--------------------------------------------------------------------------------------- | |
501 */ | |
502 /// CSampleGrabberCD destructor | |
503 static void CSampleGrabberCB_Destroy(CSampleGrabberCB * This) | |
504 { | |
505 free(This->lpVtbl); | |
506 free(This); | |
507 } | |
508 | |
509 /// CSampleGrabberCD IUnknown interface methods implementation | |
510 static long STDCALL CSampleGrabberCB_QueryInterface(ISampleGrabberCB * | |
511 This, | |
512 const GUID * riid, | |
513 void **ppvObject) | |
514 { | |
515 CSampleGrabberCB *me = (CSampleGrabberCB *) This; | |
516 GUID *r; | |
517 unsigned int i = 0; | |
518 Debug printf("CSampleGrabberCB_QueryInterface(%p) called\n", This); | |
519 if (!ppvObject) | |
520 return E_POINTER; | |
521 for (r = me->interfaces; | |
522 i < sizeof(me->interfaces) / sizeof(me->interfaces[0]); r++, i++) | |
523 if (!memcmp(r, riid, sizeof(*r))) { | |
524 OLE_CALL(This, AddRef); | |
525 *ppvObject = This; | |
526 return 0; | |
527 } | |
528 Debug printf("Query failed! (GUID: 0x%x)\n", *(unsigned int *) riid); | |
529 return E_NOINTERFACE; | |
530 } | |
531 | |
532 static long STDCALL CSampleGrabberCB_AddRef(ISampleGrabberCB * This) | |
533 { | |
534 CSampleGrabberCB *me = (CSampleGrabberCB *) This; | |
535 Debug printf("CSampleGrabberCB_AddRef(%p) called (ref:%d)\n", This, | |
536 me->refcount); | |
537 return ++(me->refcount); | |
538 } | |
539 | |
540 static long STDCALL CSampleGrabberCB_Release(ISampleGrabberCB * This) | |
541 { | |
542 CSampleGrabberCB *me = (CSampleGrabberCB *) This; | |
543 Debug printf("CSampleGrabberCB_Release(%p) called (new ref:%d)\n", | |
544 This, me->refcount - 1); | |
545 if (--(me->refcount) == 0) | |
546 CSampleGrabberCB_Destroy(me); | |
547 return 0; | |
548 } | |
549 | |
550 | |
551 HRESULT STDCALL CSampleGrabberCB_BufferCB(ISampleGrabberCB * This, | |
552 double SampleTime, | |
553 BYTE * pBuffer, long lBufferLen) | |
554 { | |
555 CSampleGrabberCB *this = (CSampleGrabberCB *) This; | |
556 grabber_ringbuffer_t *rb = this->pbuf; | |
557 | |
558 if (!lBufferLen) | |
559 return E_FAIL; | |
560 | |
561 if (!rb->ringbuffer) { | |
562 rb->buffersize /= lBufferLen; | |
563 if (init_ringbuffer(rb, rb->buffersize, lBufferLen) != S_OK) | |
564 return E_FAIL; | |
565 } | |
566 mp_msg(MSGT_TV, MSGL_DBG4, | |
567 "tvi_dshow: BufferCB(%p): len=%ld ts=%f\n", This, lBufferLen, SampleTime); | |
568 EnterCriticalSection(rb->pMutex); | |
569 if (rb->count >= rb->buffersize) { | |
570 rb->head = (rb->head + 1) % rb->buffersize; | |
571 rb->count--; | |
572 } | |
573 | |
574 memcpy(rb->ringbuffer[rb->tail], pBuffer, | |
575 lBufferLen < rb->blocksize ? lBufferLen : rb->blocksize); | |
576 rb->dpts[rb->tail] = SampleTime; | |
577 rb->tail = (rb->tail + 1) % rb->buffersize; | |
578 rb->count++; | |
579 LeaveCriticalSection(rb->pMutex); | |
580 | |
581 return S_OK; | |
582 } | |
583 | |
584 /// wrapper. directshow does the same when BufferCB callback is requested | |
585 HRESULT STDCALL CSampleGrabberCB_SampleCB(ISampleGrabberCB * This, | |
586 double SampleTime, | |
587 LPMEDIASAMPLE pSample) | |
588 { | |
589 char* buf; | |
590 long len; | |
591 long long tStart,tEnd; | |
592 HRESULT hr; | |
593 grabber_ringbuffer_t *rb = ((CSampleGrabberCB*)This)->pbuf; | |
594 | |
595 len=OLE_CALL(pSample,GetSize); | |
596 tStart=tEnd=0; | |
597 hr=OLE_CALL_ARGS(pSample,GetTime,&tStart,&tEnd); | |
598 if(FAILED(hr)){ | |
599 return hr; | |
600 } | |
601 mp_msg(MSGT_TV, MSGL_DBG4,"tvi_dshow: SampleCB(%p): %d/%d %f\n", This,rb->count,rb->buffersize,1e-7*tStart); | |
602 hr=OLE_CALL_ARGS(pSample,GetPointer,(void*)&buf); | |
603 if(FAILED(hr)){ | |
604 return hr; | |
605 } | |
606 hr=CSampleGrabberCB_BufferCB(This,1e-7*tStart,buf,len); | |
607 return hr; | |
608 | |
609 } | |
610 | |
611 /// main grabbing routine | |
612 static CSampleGrabberCB *CSampleGrabberCB_Create(grabber_ringbuffer_t * | |
613 pbuf) | |
614 { | |
615 CSampleGrabberCB *This = malloc(sizeof(CSampleGrabberCB)); | |
616 if (!This) | |
617 return NULL; | |
618 | |
619 This->lpVtbl = malloc(sizeof(ISampleGrabberVtbl)); | |
620 if (!This->lpVtbl) { | |
621 CSampleGrabberCB_Destroy(This); | |
622 return NULL; | |
623 } | |
624 This->refcount = 1; | |
625 This->lpVtbl->QueryInterface = CSampleGrabberCB_QueryInterface; | |
626 This->lpVtbl->AddRef = CSampleGrabberCB_AddRef; | |
627 This->lpVtbl->Release = CSampleGrabberCB_Release; | |
628 This->lpVtbl->SampleCB = CSampleGrabberCB_SampleCB; | |
629 This->lpVtbl->BufferCB = CSampleGrabberCB_BufferCB; | |
630 | |
631 This->interfaces[0] = IID_IUnknown; | |
632 This->interfaces[1] = IID_ISampleGrabberCB; | |
633 | |
634 This->pbuf = pbuf; | |
635 | |
636 return This; | |
637 } | |
638 | |
639 /* | |
640 *--------------------------------------------------------------------------------------- | |
641 * | |
642 * ROT related methods (register, unregister) | |
643 * | |
644 *--------------------------------------------------------------------------------------- | |
645 */ | |
646 /** | |
647 Registering graph in ROT. User will be able to connect to graph from GraphEdit. | |
648 */ | |
649 static HRESULT AddToRot(IUnknown * pUnkGraph, DWORD * pdwRegister) | |
650 { | |
651 IMoniker *pMoniker; | |
652 IRunningObjectTable *pROT; | |
653 WCHAR wsz[256]; | |
654 HRESULT hr; | |
655 | |
656 if (FAILED(GetRunningObjectTable(0, &pROT))) { | |
657 return E_FAIL; | |
658 } | |
659 wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR) pUnkGraph, | |
660 GetCurrentProcessId()); | |
661 hr = CreateItemMoniker(L"!", wsz, &pMoniker); | |
662 if (SUCCEEDED(hr)) { | |
663 hr = OLE_CALL_ARGS(pROT, Register, ROTFLAGS_REGISTRATIONKEEPSALIVE, | |
664 pUnkGraph, pMoniker, pdwRegister); | |
665 OLE_RELEASE_SAFE(pMoniker); | |
666 } | |
667 OLE_RELEASE_SAFE(pROT); | |
668 return hr; | |
669 } | |
670 | |
671 /// Unregistering graph in ROT | |
672 static void RemoveFromRot(DWORD dwRegister) | |
673 { | |
674 IRunningObjectTable *pROT; | |
675 if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) { | |
676 OLE_CALL_ARGS(pROT, Revoke, dwRegister); | |
677 OLE_RELEASE_SAFE(pROT); | |
678 } | |
679 } | |
680 | |
681 /* | |
682 *--------------------------------------------------------------------------------------- | |
683 * | |
684 * ringbuffer related methods (init, destroy) | |
685 * | |
686 *--------------------------------------------------------------------------------------- | |
687 */ | |
688 /** | |
689 * \brief ringbuffer destroying routine | |
690 * | |
691 * \param rb pointer to empty (just allocated) ringbuffer structure | |
692 * | |
693 * \note routine does not frees memory, allocated for grabber_rinbuffer_s structure | |
694 */ | |
695 static void destroy_ringbuffer(grabber_ringbuffer_t * rb) | |
696 { | |
697 int i; | |
698 | |
699 if (!rb) | |
700 return; | |
701 | |
702 if (rb->ringbuffer) { | |
703 for (i = 0; i < rb->buffersize; i++) | |
704 if (rb->ringbuffer[i]) | |
705 free(rb->ringbuffer[i]); | |
706 free(rb->ringbuffer); | |
707 rb->ringbuffer = NULL; | |
708 } | |
709 if (rb->dpts) { | |
710 free(rb->dpts); | |
711 rb->dpts = NULL; | |
712 } | |
713 if (rb->pMutex) { | |
714 DeleteCriticalSection(rb->pMutex); | |
715 free(rb->pMutex); | |
716 rb->pMutex = NULL; | |
717 } | |
718 | |
719 rb->blocksize = 0; | |
720 rb->buffersize = 0; | |
721 rb->head = 0; | |
722 rb->tail = 0; | |
723 rb->count = 0; | |
724 } | |
725 | |
726 /** | |
727 * \brief ringbuffer initialization | |
728 * | |
729 * \param rb pointer to empty (just allocated) ringbuffer structure | |
730 * \param buffersize size of buffer in blocks | |
731 * \param blocksize size of buffer's block | |
732 * | |
733 * \return S_OK if success | |
734 * \return E_OUTOFMEMORY not enough memory | |
735 * | |
736 * \note routine does not allocates memory for grabber_rinbuffer_s structure | |
737 */ | |
738 static HRESULT init_ringbuffer(grabber_ringbuffer_t * rb, int buffersize, | |
739 int blocksize) | |
740 { | |
741 int i; | |
742 | |
743 if (!rb) | |
744 return E_OUTOFMEMORY; | |
745 | |
746 rb->buffersize = buffersize < 2 ? 2 : buffersize; | |
747 rb->blocksize = blocksize; | |
748 | |
749 mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Capture buffer: %d blocks of %d bytes.\n", | |
750 rb->buffersize, rb->blocksize); | |
751 | |
752 rb->ringbuffer = (char **) malloc(rb->buffersize * sizeof(char *)); | |
753 if (!rb) | |
754 return E_POINTER; | |
755 memset(rb->ringbuffer, 0, rb->buffersize * sizeof(char *)); | |
756 | |
757 for (i = 0; i < rb->buffersize; i++) { | |
758 rb->ringbuffer[i] = (char *) malloc(rb->blocksize * sizeof(char)); | |
759 if (!rb->ringbuffer[i]) { | |
760 destroy_ringbuffer(rb); | |
761 return E_OUTOFMEMORY; | |
762 } | |
763 } | |
764 rb->dpts = (double*) malloc(rb->buffersize * sizeof(double)); | |
765 if (!rb->dpts) { | |
766 destroy_ringbuffer(rb); | |
767 return E_OUTOFMEMORY; | |
768 } | |
769 rb->head = 0; | |
770 rb->tail = 0; | |
771 rb->count = 0; | |
772 rb->tStart = -1; | |
773 rb->pMutex = (CRITICAL_SECTION *) malloc(sizeof(CRITICAL_SECTION)); | |
774 if (!rb->pMutex) { | |
775 destroy_ringbuffer(rb); | |
776 return E_OUTOFMEMORY; | |
777 } | |
778 InitializeCriticalSection(rb->pMutex); | |
779 return S_OK; | |
780 } | |
781 | |
782 /* | |
783 *--------------------------------------------------------------------------------------- | |
784 * | |
785 * Tuner related methods (frequency, capabilities, etc | |
786 * | |
787 *--------------------------------------------------------------------------------------- | |
788 */ | |
789 /** | |
790 * \brief returns string with name for givend PsysCon_* constant | |
791 * | |
792 * \param lPhysicalType constant from PhysicalConnectorType enumeration | |
793 * | |
794 * \return pointer to string with apropriate name | |
795 * | |
796 * \note | |
797 * Caller should not free returned pointer | |
798 */ | |
799 static char *physcon2str(const long lPhysicalType) | |
800 { | |
801 int i; | |
802 for(i=0; tv_physcon_types[i].name; i++) | |
803 if(tv_physcon_types[i].type==lPhysicalType) | |
804 return tv_physcon_types[i].name; | |
805 return "Unknown"; | |
806 }; | |
807 | |
808 /** | |
809 * \brief converts MPlayer's chanlist to system country code. | |
810 * | |
811 * \param chanlist MPlayer's chanlist name | |
812 * | |
813 * \return system country code | |
814 * | |
815 * \remarks | |
816 * After call to IAMTVTuner::put_CountryCode with returned value tuner switches to frequency table used in specified | |
817 * country (which is usually larger then MPlayer's one, so workaround will work fine). | |
818 * | |
819 * \todo | |
820 * Resolve trouble with cable channels (DirectShow's tuners must be switched between broadcast and cable channels modes. | |
821 */ | |
822 static int chanlist2country(char *chanlist) | |
823 { | |
824 int i; | |
825 for(i=0; tv_chanlist2country[i].chanlist_name; i++) | |
826 if (!strcmp(chanlist, tv_chanlist2country[i].chanlist_name)) | |
827 break; | |
828 return tv_chanlist2country[i].country_code; | |
829 } | |
830 | |
831 /** | |
832 * \brief loads specified resource from module and return pointer to it | |
833 * | |
834 * \param hDLL valid module desriptor | |
835 * \param index index of resource. resource with name "#<index>" will be loaded | |
836 * | |
837 * \return pointer to loader resource or NULL if error occured | |
838 */ | |
839 static void *GetRC(HMODULE hDLL, int index) | |
840 { | |
841 char szRCDATA[10]; | |
842 char szName[10]; | |
843 HRSRC hRes; | |
844 HGLOBAL hTable; | |
845 | |
846 snprintf(szRCDATA, 10, "#%d", (int)RT_RCDATA); | |
847 snprintf(szName, 10, "#%d", index); | |
848 | |
849 hRes = FindResource(hDLL, szName, szRCDATA); | |
850 if (!hRes) { | |
851 return NULL; | |
852 } | |
853 hTable = LoadResource(hDLL, hRes); | |
854 if (!hTable) { | |
855 return NULL; | |
856 } | |
857 return LockResource(hTable); | |
858 } | |
859 | |
860 /** | |
861 * \brief loads frequency table for given country from kstvtune.ax | |
862 * | |
863 * \param[in] nCountry - country code | |
864 * \param[in] nInputType (TunerInputCable or TunerInputAntenna) | |
865 * \param[out] pplFreqTable - address of variable that receives pointer to array, containing frequencies | |
866 * \param[out] pnLen length of array | |
867 * \param[out] pnFirst - channel number of first entry in array (nChannelMax) | |
868 * | |
869 * \return S_OK if success | |
870 * \return E_POINTER pplFreqTable==NULL || plFirst==NULL || pnLen==NULL | |
871 * \return E_FAIL error occured during load | |
872 * | |
873 * \remarks | |
874 * - array must be freed by caller | |
875 * - MSDN says that it is not neccessery to unlock or free resource. It will be done after unloading DLL | |
876 */ | |
877 static HRESULT load_freq_table(int nCountry, int nInputType, | |
878 long **pplFreqTable, int *pnLen, | |
879 int *pnFirst) | |
880 { | |
881 HMODULE hDLL; | |
882 long *plFreqTable; | |
883 TRCCountryList *pCountryList; | |
884 int i, index; | |
885 | |
886 mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: load_freq_table called %d (%d)\n",nCountry,nInputType); | |
887 /* ASSERT(sizeof(TRCCountryList)==10); // need properly aligned structure */ | |
888 | |
889 if (!pplFreqTable || !pnFirst || !pnLen) | |
890 return E_POINTER; | |
891 if (!nCountry) | |
892 return E_FAIL; | |
893 | |
894 hDLL = LoadLibrary("kstvtune.ax"); | |
895 if (!hDLL) { | |
896 return E_FAIL; | |
897 } | |
898 pCountryList = GetRC(hDLL, 9999); | |
899 if (!pCountryList) { | |
900 FreeLibrary(hDLL); | |
901 return E_FAIL; | |
902 } | |
903 for (i = 0; pCountryList[i].CountryCode != 0; i++) | |
904 if (pCountryList[i].CountryCode == nCountry) | |
905 break; | |
906 if (pCountryList[i].CountryCode == 0) { | |
907 FreeLibrary(hDLL); | |
908 return E_FAIL; | |
909 } | |
910 if (nInputType == TunerInputCable) | |
911 index = pCountryList[i].CableFreqTable; | |
912 else | |
913 index = pCountryList[i].BroadcastFreqTable; | |
914 | |
915 plFreqTable = GetRC(hDLL, index); //First element is number of first channel, second - number of last channel | |
916 if (!plFreqTable) { | |
917 FreeLibrary(hDLL); | |
918 return E_FAIL; | |
919 } | |
920 *pnFirst = plFreqTable[0]; | |
921 *pnLen = (int) (plFreqTable[1] - plFreqTable[0] + 1); | |
922 *pplFreqTable = (long *) malloc((*pnLen) * sizeof(long)); | |
923 if (!*pplFreqTable) { | |
924 FreeLibrary(hDLL); | |
925 return E_FAIL; | |
926 } | |
927 for (i = 0; i < *pnLen; i++) { | |
928 (*pplFreqTable)[i] = plFreqTable[i + 2]; | |
929 } | |
930 FreeLibrary(hDLL); | |
931 return S_OK; | |
932 } | |
933 | |
934 /** | |
935 * \brief tunes to given frequency through IKsPropertySet call | |
936 * | |
937 * \param pTVTuner IAMTVTuner interface of capture device | |
938 * \param lFreq frequency to tune (in Hz) | |
939 * | |
940 * \return S_OK success | |
941 * \return apropriate error code otherwise | |
942 * | |
943 * \note | |
944 * Due to either bug in driver or error in following code calll to IKsProperty::Set | |
945 * in this methods always fail with error 0x8007007a. | |
946 * | |
947 * \todo test code on other machines and an error | |
948 */ | |
949 static HRESULT set_frequency_direct(IAMTVTuner * pTVTuner, long lFreq) | |
950 { | |
951 HRESULT hr; | |
952 DWORD dwSupported = 0; | |
953 DWORD cbBytes = 0; | |
954 KSPROPERTY_TUNER_MODE_CAPS_S mode_caps; | |
955 KSPROPERTY_TUNER_FREQUENCY_S frequency; | |
956 IKsPropertySet *pKSProp; | |
957 | |
958 mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: set_frequency_direct called\n"); | |
959 | |
960 memset(&mode_caps, 0, sizeof(mode_caps)); | |
961 memset(&frequency, 0, sizeof(frequency)); | |
962 | |
963 hr = OLE_QUERYINTERFACE(pTVTuner, IID_IKsPropertySet, pKSProp); | |
964 if (FAILED(hr)) | |
965 return hr; //no IKsPropertySet interface | |
966 | |
967 mode_caps.Mode = AMTUNER_MODE_TV; | |
968 hr = OLE_CALL_ARGS(pKSProp, QuerySupported, &PROPSETID_TUNER, | |
969 KSPROPERTY_TUNER_MODE_CAPS, &dwSupported); | |
970 if (FAILED(hr)) { | |
971 OLE_RELEASE_SAFE(pKSProp); | |
972 return hr; | |
973 } | |
974 | |
975 if (!dwSupported & KSPROPERTY_SUPPORT_GET) { | |
976 OLE_RELEASE_SAFE(pKSProp); | |
977 return E_FAIL; //PROPSETID_TINER not supported | |
978 } | |
979 | |
980 hr = OLE_CALL_ARGS(pKSProp, Get, &PROPSETID_TUNER, | |
981 KSPROPERTY_TUNER_MODE_CAPS, | |
982 INSTANCEDATA_OF_PROPERTY_PTR(&mode_caps), | |
983 INSTANCEDATA_OF_PROPERTY_SIZE(mode_caps), | |
984 &mode_caps, sizeof(mode_caps), &cbBytes); | |
985 | |
986 frequency.Frequency = lFreq; | |
987 | |
988 if (mode_caps.Strategy == KS_TUNER_STRATEGY_DRIVER_TUNES) | |
989 frequency.TuningFlags = KS_TUNER_TUNING_FINE; | |
990 else | |
991 frequency.TuningFlags = KS_TUNER_TUNING_EXACT; | |
992 | |
993 if (lFreq < mode_caps.MinFrequency || lFreq > mode_caps.MaxFrequency) { | |
994 OLE_RELEASE_SAFE(pKSProp); | |
995 return E_FAIL; | |
996 } | |
997 | |
998 hr = OLE_CALL_ARGS(pKSProp, Set, &PROPSETID_TUNER, | |
999 KSPROPERTY_TUNER_FREQUENCY, | |
1000 INSTANCEDATA_OF_PROPERTY_PTR(&frequency), | |
1001 INSTANCEDATA_OF_PROPERTY_SIZE(frequency), | |
1002 &frequency, sizeof(frequency)); | |
1003 if (FAILED(hr)) { | |
1004 OLE_RELEASE_SAFE(pKSProp); | |
1005 return hr; | |
1006 } | |
1007 | |
1008 OLE_RELEASE_SAFE(pKSProp); | |
1009 | |
1010 return S_OK; | |
1011 } | |
1012 | |
1013 /** | |
1014 * \brief find channel with nearest frequency and set it | |
1015 * | |
1016 * \param priv driver's private data | |
1017 * \param lFreq frequency in Hz | |
1018 * | |
1019 * \return S_OK if success | |
1020 * \return E_FAIL if error occured | |
1021 */ | |
1022 static HRESULT set_nearest_freq(priv_t * priv, long lFreq) | |
1023 { | |
1024 HRESULT hr; | |
1025 int i; | |
1026 long lFreqDiff=-1; | |
1027 int nChannel; | |
1028 TunerInputType tunerInput; | |
1029 long lInput; | |
1030 | |
1031 mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: set_nearest_freq called\n"); | |
1032 if(priv->freq_table_len == -1 && !priv->freq_table) { | |
1033 | |
1034 hr = OLE_CALL_ARGS(priv->pTVTuner, get_ConnectInput, &lInput); | |
1035 if(FAILED(hr)){ //Falling back to 0 | |
1036 lInput=0; | |
1037 } | |
1038 | |
1039 hr = OLE_CALL_ARGS(priv->pTVTuner, get_InputType, lInput, &tunerInput); | |
1040 | |
1041 if (load_freq_table(chanlist2country(priv->tv_param->chanlist), tunerInput, &(priv->freq_table), &(priv->freq_table_len), &(priv->first_channel)) != S_OK) {//FIXME | |
1042 priv->freq_table_len=0; | |
1043 priv->freq_table=NULL; | |
1044 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TVI_DS_UnableExtractFreqTable); | |
1045 return E_FAIL; | |
1046 }; | |
1047 mp_msg(MSGT_TV, MSGL_V, MSGTR_TVI_DS_FreqTableLoaded, tunerInput == TunerInputAntenna ? "broadcast" : "cable", | |
1048 chanlist2country(priv->tv_param->chanlist), priv->freq_table_len); | |
1049 } | |
1050 | |
1051 if (priv->freq_table_len <= 0) | |
1052 return E_FAIL; | |
1053 | |
1054 //FIXME: rewrite search algo | |
1055 nChannel = -1; | |
1056 for (i = 0; i < priv->freq_table_len; i++) { | |
1057 if (nChannel == -1 || labs(lFreq - priv->freq_table[i]) < lFreqDiff) { | |
1058 nChannel = priv->first_channel + i; | |
1059 lFreqDiff = labs(lFreq - priv->freq_table[i]); | |
1060 } | |
1061 } | |
1062 if (nChannel == -1) { | |
1063 mp_msg(MSGT_TV,MSGL_ERR, MSGTR_TVI_DS_UnableFindNearestChannel); | |
1064 return E_FAIL; | |
1065 } | |
1066 hr = OLE_CALL_ARGS(priv->pTVTuner, put_Channel, nChannel, | |
1067 AMTUNER_SUBCHAN_DEFAULT, AMTUNER_SUBCHAN_DEFAULT); | |
1068 if (FAILED(hr)) { | |
1069 mp_msg(MSGT_TV,MSGL_ERR,MSGTR_TVI_DS_UnableToSetChannel, (unsigned int)hr); | |
1070 return E_FAIL; | |
1071 } | |
1072 return S_OK; | |
1073 } | |
1074 | |
1075 /** | |
1076 * \brief setting frequency. decides whether use direct call/workaround | |
1077 * | |
1078 * \param priv driver's private data | |
1079 * \param lFreq frequency in Hz | |
1080 * | |
1081 * \return TVI_CONTROL_TRUE if success | |
1082 * \return TVI_CONTROL_FALSE if error occured | |
1083 * | |
1084 * \todo check for freq boundary | |
1085 */ | |
1086 static int set_frequency(priv_t * priv, long lFreq) | |
1087 { | |
1088 HRESULT hr; | |
1089 | |
1090 mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: set_frequency called\n"); | |
1091 if (!priv->pTVTuner) | |
1092 return TVI_CONTROL_FALSE; | |
1093 if (priv->direct_setfreq_call) { //using direct call to set frequency | |
1094 hr = set_frequency_direct(priv->pTVTuner, lFreq); | |
1095 if (FAILED(hr)) { | |
1096 mp_msg(MSGT_TV, MSGL_V, MSGTR_TVI_DS_DirectSetFreqFailed); | |
1097 priv->direct_setfreq_call = 0; | |
1098 } | |
1099 } | |
1100 if (!priv->direct_setfreq_call) { | |
1101 hr = set_nearest_freq(priv, lFreq); | |
1102 } | |
1103 if (FAILED(hr)) | |
1104 return TVI_CONTROL_FALSE; | |
1105 #ifdef DEPRECATED | |
1106 priv->pGrabber->ClearBuffer(priv->pGrabber); | |
1107 #endif | |
1108 return TVI_CONTROL_TRUE; | |
1109 } | |
1110 | |
1111 /** | |
1112 * \brief return current frequency from tuner (in Hz) | |
1113 * | |
1114 * \param pTVTuner IAMTVTuner interface of tuner | |
1115 * \param plFreq address of variable that receives current frequency | |
1116 * | |
1117 * \return S_OK success | |
1118 * \return E_POINTER pTVTuner==NULL || plFreq==NULL | |
1119 * \return apropriate error code otherwise | |
1120 */ | |
1121 static HRESULT get_frequency_direct(IAMTVTuner * pTVTuner, long *plFreq) | |
1122 { | |
1123 HRESULT hr; | |
1124 KSPROPERTY_TUNER_STATUS_S TunerStatus; | |
1125 DWORD cbBytes; | |
1126 IKsPropertySet *pKSProp; | |
1127 mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: get_frequency_direct called\n"); | |
1128 | |
1129 if (!plFreq) | |
1130 return E_POINTER; | |
1131 | |
1132 hr = OLE_QUERYINTERFACE(pTVTuner, IID_IKsPropertySet, pKSProp); | |
1133 if (FAILED(hr)) { | |
1134 mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Get freq QueryInterface failed\n"); | |
1135 return hr; | |
1136 } | |
1137 | |
1138 hr = OLE_CALL_ARGS(pKSProp, Get, &PROPSETID_TUNER, | |
1139 KSPROPERTY_TUNER_STATUS, | |
1140 INSTANCEDATA_OF_PROPERTY_PTR(&TunerStatus), | |
1141 INSTANCEDATA_OF_PROPERTY_SIZE(TunerStatus), | |
1142 &TunerStatus, sizeof(TunerStatus), &cbBytes); | |
1143 if (FAILED(hr)) { | |
1144 mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Get freq Get failure\n"); | |
1145 return hr; | |
1146 } | |
1147 *plFreq = TunerStatus.CurrentFrequency; | |
1148 return S_OK; | |
1149 } | |
1150 | |
1151 /** | |
1152 * \brief gets current frequency | |
1153 * | |
1154 * \param priv driver's private data structure | |
1155 * \param plFreq - pointer to long int to store frequency to (in Hz) | |
1156 * | |
1157 * \return TVI_CONTROL_TRUE if success, TVI_CONTROL_FALSE otherwise | |
1158 */ | |
1159 static int get_frequency(priv_t * priv, long *plFreq) | |
1160 { | |
1161 HRESULT hr; | |
1162 | |
1163 mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: get_frequency called\n"); | |
1164 | |
1165 if (!plFreq || !priv->pTVTuner) | |
1166 return TVI_CONTROL_FALSE; | |
1167 | |
1168 if (priv->direct_getfreq_call) { //using direct call to get frequency | |
1169 hr = get_frequency_direct(priv->pTVTuner, plFreq); | |
1170 if (FAILED(hr)) { | |
1171 mp_msg(MSGT_TV, MSGL_INFO, MSGTR_TVI_DS_DirectGetFreqFailed); | |
1172 priv->direct_getfreq_call = 0; | |
1173 } | |
1174 } | |
1175 if (!priv->direct_getfreq_call) { | |
1176 hr=OLE_CALL_ARGS(priv->pTVTuner, get_VideoFrequency, plFreq); | |
1177 if (FAILED(hr)) | |
1178 return TVI_CONTROL_FALSE; | |
1179 | |
1180 } | |
1181 return TVI_CONTROL_TRUE; | |
1182 } | |
1183 | |
1184 /** | |
1185 * \brief get tuner capabilities | |
1186 * | |
1187 * \param priv driver's private data | |
1188 */ | |
1189 static void get_capabilities(priv_t * priv) | |
1190 { | |
1191 long lAvailableFormats; | |
1192 HRESULT hr; | |
1193 int i; | |
1194 long lInputPins, lOutputPins, lRelated, lPhysicalType; | |
1195 IEnumPins *pEnum; | |
1196 char tmp[200]; | |
1197 IPin *pPin = 0; | |
1198 PIN_DIRECTION ThisPinDir; | |
1199 PIN_INFO pi; | |
1200 IAMAudioInputMixer *pIAMixer; | |
1201 | |
1202 mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: get_capabilities called\n"); | |
1203 if (priv->pTVTuner) { | |
1204 | |
1205 mp_msg(MSGT_TV, MSGL_V, MSGTR_TVI_DS_SupportedNorms); | |
1206 hr = OLE_CALL_ARGS(priv->pTVTuner, get_AvailableTVFormats, | |
1207 &lAvailableFormats); | |
1208 if (FAILED(hr)) | |
1209 tv_available_norms_count = 0; | |
1210 else { | |
1211 for (i = 0; i < TV_NORMS_COUNT; i++) { | |
1212 if (lAvailableFormats & tv_norms[i].index) { | |
1213 tv_available_norms[tv_available_norms_count] = i; | |
1214 mp_msg(MSGT_TV, MSGL_V, " %d=%s;", | |
1215 tv_available_norms_count + 1, tv_norms[i].name); | |
1216 tv_available_norms_count++; | |
1217 } | |
1218 } | |
1219 } | |
1220 mp_msg(MSGT_TV, MSGL_INFO, "\n"); | |
1221 } | |
1222 if (priv->pCrossbar) { | |
1223 OLE_CALL_ARGS(priv->pCrossbar, get_PinCounts, &lOutputPins, | |
1224 &lInputPins); | |
1225 | |
1226 tv_available_inputs = (long *) malloc(sizeof(long) * lInputPins); | |
1227 tv_available_inputs_count = 0; | |
1228 | |
1229 mp_msg(MSGT_TV, MSGL_V, MSGTR_TVI_DS_AvailableVideoInputs); | |
1230 for (i = 0; i < lInputPins; i++) { | |
1231 OLE_CALL_ARGS(priv->pCrossbar, get_CrossbarPinInfo, 1, i, | |
1232 &lRelated, &lPhysicalType); | |
1233 | |
1234 if (lPhysicalType < 0x1000) { | |
1235 tv_available_inputs[tv_available_inputs_count++] = i; | |
1236 mp_msg(MSGT_TV, MSGL_V, " %d=%s;", | |
1237 tv_available_inputs_count - 1, | |
1238 physcon2str(lPhysicalType)); | |
1239 } | |
1240 } | |
1241 mp_msg(MSGT_TV, MSGL_INFO, "\n"); | |
1242 | |
1243 set_crossbar_input(priv, 0); | |
1244 } | |
1245 | |
1246 if (priv->adev_index != -1) { | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
1247 hr = OLE_CALL_ARGS(priv->chains[1]->pCaptureFilter, EnumPins, &pEnum); |
24744 | 1248 if (FAILED(hr)) |
1249 return; | |
1250 mp_msg(MSGT_TV, MSGL_V, MSGTR_TVI_DS_AvailableAudioInputs); | |
1251 i = 0; | |
1252 while (OLE_CALL_ARGS(pEnum, Next, 1, &pPin, NULL) == S_OK) { | |
1253 memset(&pi, 0, sizeof(pi)); | |
1254 memset(tmp, 0, 200); | |
1255 OLE_CALL_ARGS(pPin, QueryDirection, &ThisPinDir); | |
1256 if (ThisPinDir == PINDIR_INPUT) { | |
1257 OLE_CALL_ARGS(pPin, QueryPinInfo, &pi); | |
1258 wtoa(pi.achName, tmp, 200); | |
1259 OLE_RELEASE_SAFE(pi.pFilter); | |
1260 mp_msg(MSGT_TV, MSGL_V, " %d=%s", i, tmp); | |
1261 mp_msg(MSGT_TV, MSGL_DBG3, " (%p)", pPin); | |
1262 hr = OLE_QUERYINTERFACE(pPin, IID_IAMAudioInputMixer,pIAMixer); | |
1263 if (SUCCEEDED(hr)) { | |
1264 if (i == priv->tv_param->audio_id) { | |
1265 OLE_CALL_ARGS(pIAMixer, put_Enable, TRUE); | |
1266 if(priv->tv_param->volume>0) | |
1267 OLE_CALL_ARGS(pIAMixer, put_MixLevel, 0.01 * priv->tv_param->volume); | |
1268 #if 0 | |
1269 else | |
1270 OLE_CALL_ARGS(pIAMixer, put_MixLevel, 1.0); | |
1271 #endif | |
1272 mp_msg(MSGT_TV, MSGL_V, MSGTR_TVI_DS_InputSelected); | |
1273 } else { | |
1274 OLE_CALL_ARGS(pIAMixer, put_Enable, FALSE); | |
1275 #if 0 | |
1276 OLE_CALL_ARGS(pIAMixer, put_MixLevel, 0.0); | |
1277 #endif | |
1278 } | |
1279 OLE_RELEASE_SAFE(pIAMixer); | |
1280 } | |
1281 mp_msg(MSGT_TV, MSGL_V, ";"); | |
1282 OLE_RELEASE_SAFE(pPin); | |
1283 i++; | |
1284 } | |
1285 } | |
1286 mp_msg(MSGT_TV, MSGL_INFO, "\n"); | |
1287 OLE_RELEASE_SAFE(pEnum); | |
1288 } | |
1289 } | |
1290 | |
1291 /* | |
1292 *--------------------------------------------------------------------------------------- | |
1293 * | |
1294 * Filter related methods | |
1295 * | |
1296 *--------------------------------------------------------------------------------------- | |
1297 */ | |
1298 /** | |
25087
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1299 * \brief routine for reconnecting two pins with new media type |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1300 * \param pGraph IGraphBuilder interface |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1301 * \param chan chain data |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1302 * \param pmt [in/out] new mediatype for pin connection |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1303 * |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1304 * \return S_OK if operation successfult, error code otherwise |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1305 * will also return media type of new connection into pmt variable |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1306 */ |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1307 static HRESULT reconnect_pins(IGraphBuilder *pGraph, chain_t *chain, AM_MEDIA_TYPE *pmt) |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1308 { |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1309 AM_MEDIA_TYPE old_mt; |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1310 HRESULT hr; |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1311 |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1312 do { |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1313 /* save old media type for reconnection in case of error */ |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1314 hr = OLE_CALL_ARGS(chain->pCapturePin, ConnectionMediaType, &old_mt); |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1315 if(FAILED(hr)) |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1316 return hr; |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1317 |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1318 hr = OLE_CALL(chain->pCapturePin, Disconnect); |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1319 if(FAILED(hr)) |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1320 return hr; |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1321 |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1322 hr = OLE_CALL_ARGS(chain->pSG, SetMediaType, pmt); |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1323 if(FAILED(hr)) |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1324 return hr; |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1325 |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1326 hr = OLE_CALL_ARGS(pGraph, Connect, chain->pCapturePin, chain->pSGIn); |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1327 if(FAILED(hr)) |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1328 { |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1329 OLE_CALL_ARGS(chain->pSG, SetMediaType, &old_mt); |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1330 OLE_CALL_ARGS(pGraph, Connect, chain->pCapturePin, chain->pSGIn); |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1331 break; |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1332 } |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1333 hr = OLE_CALL_ARGS(chain->pCapturePin, ConnectionMediaType, &old_mt); |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1334 |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1335 hr = S_OK; |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1336 } while(0); |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1337 |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1338 FreeMediaType(pmt); |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1339 CopyMediaType(pmt, &old_mt); |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1340 FreeMediaType(&old_mt); |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1341 return hr; |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1342 } |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1343 |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1344 /** |
24744 | 1345 * \brief building in graph audio/video capture chain |
1346 * | |
1347 * \param priv driver's private data | |
1348 * \param pCaptureFilter pointer to capture device's IBaseFilter interface | |
1349 * \param pbuf ringbuffer data structure | |
1350 * \param pmt media type for chain (AM_MEDIA_TYPE) | |
1351 * | |
1352 * \note routine does not frees memory, allocated for grabber_rinbuffer_s structure | |
1353 */ | |
25084
f72ebba1e6d1
pass chain structure instead of several variables to build_sub_graph
voroshil
parents:
25083
diff
changeset
|
1354 static HRESULT build_sub_graph(priv_t * priv, chain_t * chain, const GUID* ppin_category) |
24744 | 1355 { |
1356 HRESULT hr; | |
25063
29260745e4fa
Pass all available formats to chain building routine and
voroshil
parents:
25061
diff
changeset
|
1357 int nFormatProbed = 0; |
25029
c9f20e41bc13
Make sure that mplayer will receive actual media type
voroshil
parents:
25028
diff
changeset
|
1358 |
24744 | 1359 IPin *pSGOut; |
1360 IPin *pNRIn=NULL; | |
1361 | |
1362 IBaseFilter *pNR = NULL; | |
1363 | |
1364 hr=S_OK; | |
25063
29260745e4fa
Pass all available formats to chain building routine and
voroshil
parents:
25061
diff
changeset
|
1365 |
29260745e4fa
Pass all available formats to chain building routine and
voroshil
parents:
25061
diff
changeset
|
1366 //No supported formats |
25084
f72ebba1e6d1
pass chain structure instead of several variables to build_sub_graph
voroshil
parents:
25083
diff
changeset
|
1367 if(!chain->arpmt[0]) |
25063
29260745e4fa
Pass all available formats to chain building routine and
voroshil
parents:
25061
diff
changeset
|
1368 return E_FAIL; |
29260745e4fa
Pass all available formats to chain building routine and
voroshil
parents:
25061
diff
changeset
|
1369 |
24744 | 1370 do{ |
1371 hr = OLE_CALL_ARGS(priv->pBuilder, FindPin, | |
25084
f72ebba1e6d1
pass chain structure instead of several variables to build_sub_graph
voroshil
parents:
25083
diff
changeset
|
1372 (IUnknown *) chain->pCaptureFilter, |
24744 | 1373 PINDIR_OUTPUT, ppin_category, |
25087
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1374 chain->majortype, FALSE, 0, &chain->pCapturePin); |
24744 | 1375 if(FAILED(hr)){ |
1376 mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: FindPin(pCapturePin) call failed. Error:0x%x\n", (unsigned int)hr); | |
1377 break; | |
1378 } | |
1379 /* Addinf SampleGrabber filter for video stream */ | |
25087
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1380 hr = CoCreateInstance((GUID *) & CLSID_SampleGrabber, NULL,CLSCTX_INPROC_SERVER, &IID_IBaseFilter,(void *) &chain->pSGF); |
24744 | 1381 if(FAILED(hr)){ |
1382 mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: CoCreateInstance(SampleGrabber) call failed. Error:0x%x\n", (unsigned int)hr); | |
1383 break; | |
1384 } | |
25087
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1385 hr = OLE_CALL_ARGS(priv->pGraph, AddFilter, chain->pSGF, L"Sample Grabber"); |
24744 | 1386 if(FAILED(hr)){ |
1387 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: AddFilter(SampleGrabber) call failed. Error:0x%x\n", (unsigned int)hr); | |
1388 break; | |
1389 } | |
25087
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1390 hr = OLE_CALL_ARGS(priv->pBuilder, FindPin, (IUnknown *) chain->pSGF,PINDIR_INPUT, NULL, NULL, FALSE, 0, &chain->pSGIn); |
24744 | 1391 if(FAILED(hr)){ |
1392 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: FindPin(pSGIn) call failed. Error:0x%x\n", (unsigned int)hr); | |
1393 break; | |
1394 } | |
25087
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1395 hr = OLE_CALL_ARGS(priv->pBuilder, FindPin, (IUnknown *) chain->pSGF,PINDIR_OUTPUT, NULL, NULL, FALSE, 0, &pSGOut); |
24744 | 1396 if(FAILED(hr)){ |
1397 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: FindPin(pSGOut) call failed. Error:0x%x\n", (unsigned int)hr); | |
1398 break; | |
1399 } | |
1400 | |
1401 /* creating ringbuffer for video samples */ | |
25086
e91503fbf524
Move pointer to SampleGrabber filter into chain structure.
voroshil
parents:
25085
diff
changeset
|
1402 chain->pCSGCB = CSampleGrabberCB_Create(chain->rbuf); |
e91503fbf524
Move pointer to SampleGrabber filter into chain structure.
voroshil
parents:
25085
diff
changeset
|
1403 if(!chain->pCSGCB){ |
24744 | 1404 mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: CSampleGrabberCB_Create(pbuf) call failed. Error:0x%x\n", (unsigned int)E_OUTOFMEMORY); |
1405 break; | |
1406 } | |
1407 | |
1408 /* initializing SampleGrabber filter */ | |
25087
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1409 hr = OLE_QUERYINTERFACE(chain->pSGF, IID_ISampleGrabber, chain->pSG); |
24744 | 1410 if(FAILED(hr)){ |
1411 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: QueryInterface(IID_ISampleGrabber) call failed. Error:0x%x\n", (unsigned int)hr); | |
1412 break; | |
1413 } | |
1414 // hr = OLE_CALL_ARGS(pSG, SetCallback, (ISampleGrabberCB *) pCSGCB, 1); //we want to receive copy of sample's data | |
25087
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1415 hr = OLE_CALL_ARGS(chain->pSG, SetCallback, (ISampleGrabberCB *) chain->pCSGCB, 0); //we want to receive sample |
24744 | 1416 |
1417 if(FAILED(hr)){ | |
1418 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: SetCallback(pSG) call failed. Error:0x%x\n", (unsigned int)hr); | |
1419 break; | |
1420 } | |
25087
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1421 hr = OLE_CALL_ARGS(chain->pSG, SetOneShot, FALSE); //... for all frames |
24744 | 1422 if(FAILED(hr)){ |
1423 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: SetOneShot(pSG) call failed. Error:0x%x\n", (unsigned int)hr); | |
1424 break; | |
1425 } | |
25087
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1426 hr = OLE_CALL_ARGS(chain->pSG, SetBufferSamples, FALSE); //... do not buffer samples in sample grabber |
24744 | 1427 if(FAILED(hr)){ |
1428 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: SetBufferSamples(pSG) call failed. Error:0x%x\n", (unsigned int)hr); | |
1429 break; | |
1430 } | |
25084
f72ebba1e6d1
pass chain structure instead of several variables to build_sub_graph
voroshil
parents:
25083
diff
changeset
|
1431 |
f72ebba1e6d1
pass chain structure instead of several variables to build_sub_graph
voroshil
parents:
25083
diff
changeset
|
1432 if(priv->tv_param->normalize_audio_chunks && chain->type==audio){ |
25087
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1433 set_buffer_preference(20,(WAVEFORMATEX*)(chain->arpmt[nFormatProbed]->pbFormat),chain->pCapturePin,chain->pSGIn); |
25048 | 1434 } |
24744 | 1435 |
25084
f72ebba1e6d1
pass chain structure instead of several variables to build_sub_graph
voroshil
parents:
25083
diff
changeset
|
1436 for(nFormatProbed=0; chain->arpmt[nFormatProbed]; nFormatProbed++) |
25065 | 1437 { |
25084
f72ebba1e6d1
pass chain structure instead of several variables to build_sub_graph
voroshil
parents:
25083
diff
changeset
|
1438 DisplayMediaType("Probing format", chain->arpmt[nFormatProbed]); |
25087
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1439 hr = OLE_CALL_ARGS(chain->pSG, SetMediaType, chain->arpmt[nFormatProbed]); //set desired mediatype |
25066 | 1440 if(FAILED(hr)){ |
1441 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: SetMediaType(pSG) call failed. Error:0x%x\n", (unsigned int)hr); | |
1442 continue; | |
1443 } | |
1444 /* connecting filters together: VideoCapture --> SampleGrabber */ | |
25087
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1445 hr = OLE_CALL_ARGS(priv->pGraph, Connect, chain->pCapturePin, chain->pSGIn); |
25066 | 1446 if(FAILED(hr)){ |
1447 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: Unable to create pCapturePin<->pSGIn connection. Error:0x%x\n", (unsigned int)hr); | |
1448 continue; | |
1449 } | |
25065 | 1450 break; |
1451 } | |
1452 | |
25084
f72ebba1e6d1
pass chain structure instead of several variables to build_sub_graph
voroshil
parents:
25083
diff
changeset
|
1453 if(!chain->arpmt[nFormatProbed]) |
25065 | 1454 { |
1455 mp_msg(MSGT_TV, MSGL_WARN, "tvi_dshow: Unable to negotiate media format\n"); | |
1456 hr = E_FAIL; | |
24744 | 1457 break; |
1458 } | |
25063
29260745e4fa
Pass all available formats to chain building routine and
voroshil
parents:
25061
diff
changeset
|
1459 |
25087
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1460 hr = OLE_CALL_ARGS(chain->pCapturePin, ConnectionMediaType, chain->pmt); |
25029
c9f20e41bc13
Make sure that mplayer will receive actual media type
voroshil
parents:
25028
diff
changeset
|
1461 if(FAILED(hr)) |
c9f20e41bc13
Make sure that mplayer will receive actual media type
voroshil
parents:
25028
diff
changeset
|
1462 { |
c9f20e41bc13
Make sure that mplayer will receive actual media type
voroshil
parents:
25028
diff
changeset
|
1463 mp_msg(MSGT_TV, MSGL_WARN, MSGTR_TVI_DS_GetActualMediatypeFailed, (unsigned int)hr); |
c9f20e41bc13
Make sure that mplayer will receive actual media type
voroshil
parents:
25028
diff
changeset
|
1464 } |
24744 | 1465 |
1466 if(priv->tv_param->hidden_video_renderer){ | |
1467 IEnumFilters* pEnum; | |
1468 IBaseFilter* pFilter; | |
1469 | |
25087
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
1470 hr=OLE_CALL_ARGS(priv->pBuilder,RenderStream,NULL,NULL,(IUnknown*)chain->pCapturePin,NULL,NULL); |
24744 | 1471 |
1472 OLE_CALL_ARGS(priv->pGraph, EnumFilters, &pEnum); | |
1473 while (OLE_CALL_ARGS(pEnum, Next, 1, &pFilter, NULL) == S_OK) { | |
1474 LPVIDEOWINDOW pVideoWindow; | |
1475 hr = OLE_QUERYINTERFACE(pFilter, IID_IVideoWindow, pVideoWindow); | |
1476 if (SUCCEEDED(hr)) | |
1477 { | |
1478 OLE_CALL_ARGS(pVideoWindow,put_Visible,/* OAFALSE*/ 0); | |
1479 OLE_CALL_ARGS(pVideoWindow,put_AutoShow,/* OAFALSE*/ 0); | |
1480 OLE_RELEASE_SAFE(pVideoWindow); | |
1481 } | |
1482 OLE_RELEASE_SAFE(pFilter); | |
1483 } | |
1484 OLE_RELEASE_SAFE(pEnum); | |
1485 }else | |
1486 { | |
25052
7b2b17b57cf7
Disable terminating directshow chains with NullRenderer filter,
voroshil
parents:
25051
diff
changeset
|
1487 #if 0 |
7b2b17b57cf7
Disable terminating directshow chains with NullRenderer filter,
voroshil
parents:
25051
diff
changeset
|
1488 /* |
7b2b17b57cf7
Disable terminating directshow chains with NullRenderer filter,
voroshil
parents:
25051
diff
changeset
|
1489 Code below is disabled, because terminating chain with NullRenderer leads to jerky video. |
7b2b17b57cf7
Disable terminating directshow chains with NullRenderer filter,
voroshil
parents:
25051
diff
changeset
|
1490 Perhaps, this happens because NullRenderer filter discards each received |
7b2b17b57cf7
Disable terminating directshow chains with NullRenderer filter,
voroshil
parents:
25051
diff
changeset
|
1491 frame while discarded frames causes live source filter to dramatically reduce frame rate. |
7b2b17b57cf7
Disable terminating directshow chains with NullRenderer filter,
voroshil
parents:
25051
diff
changeset
|
1492 */ |
24744 | 1493 /* adding sink for video stream */ |
1494 hr = CoCreateInstance((GUID *) & CLSID_NullRenderer, NULL,CLSCTX_INPROC_SERVER, &IID_IBaseFilter,(void *) &pNR); | |
1495 if(FAILED(hr)){ | |
1496 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: CoCreateInstance(NullRenderer) call failed. Error:0x%x\n", (unsigned int)hr); | |
1497 break; | |
1498 } | |
1499 hr = OLE_CALL_ARGS(priv->pGraph, AddFilter, pNR, L"Null Renderer"); | |
1500 if(FAILED(hr)){ | |
1501 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: AddFilter(NullRenderer) call failed. Error:0x%x\n", (unsigned int)hr); | |
1502 break; | |
1503 } | |
1504 hr = OLE_CALL_ARGS(priv->pBuilder, FindPin, (IUnknown *) pNR,PINDIR_INPUT, NULL, NULL, FALSE, 0, &pNRIn); | |
1505 if(FAILED(hr)){ | |
1506 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: FindPin(pNRIn) call failed. Error:0x%x\n", (unsigned int)hr); | |
1507 break; | |
1508 } | |
1509 /* | |
1510 Prevent ending VBI chain with NullRenderer filter, because this causes VBI pin disconnection | |
1511 */ | |
25063
29260745e4fa
Pass all available formats to chain building routine and
voroshil
parents:
25061
diff
changeset
|
1512 if(memcmp(&(arpmt[nFormatProbed]->majortype),&MEDIATYPE_VBI,16)){ |
24744 | 1513 /* connecting filters together: SampleGrabber --> NullRenderer */ |
1514 hr = OLE_CALL_ARGS(priv->pGraph, Connect, pSGOut, pNRIn); | |
1515 if(FAILED(hr)){ | |
1516 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: Unable to create pSGOut<->pNRIn connection. Error:0x%x\n", (unsigned int)hr); | |
1517 break; | |
1518 } | |
1519 } | |
25052
7b2b17b57cf7
Disable terminating directshow chains with NullRenderer filter,
voroshil
parents:
25051
diff
changeset
|
1520 #endif |
24744 | 1521 } |
1522 | |
1523 hr = S_OK; | |
1524 } while(0); | |
25029
c9f20e41bc13
Make sure that mplayer will receive actual media type
voroshil
parents:
25028
diff
changeset
|
1525 |
24744 | 1526 OLE_RELEASE_SAFE(pSGOut); |
1527 OLE_RELEASE_SAFE(pNR); | |
1528 OLE_RELEASE_SAFE(pNRIn); | |
1529 | |
1530 return hr; | |
1531 } | |
1532 | |
1533 /** | |
1534 * \brief configures crossbar for grabbing video stream from given input | |
1535 * | |
1536 * \param priv driver's private data | |
1537 * \param input index of available video input to get data from | |
1538 * | |
1539 * \return TVI_CONTROL_TRUE success | |
1540 * \return TVI_CONTROL_FALSE error | |
1541 */ | |
1542 static int set_crossbar_input(priv_t * priv, int input) | |
1543 { | |
1544 HRESULT hr; | |
1545 int i, nVideoDecoder, nAudioDecoder; | |
1546 long lInput, lInputRelated, lRelated, lPhysicalType, lOutputPins, | |
1547 lInputPins; | |
1548 | |
1549 mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: Configuring crossbar\n"); | |
1550 if (!priv->pCrossbar || input < 0 | |
1551 || input >= tv_available_inputs_count) | |
1552 return TVI_CONTROL_FALSE; | |
1553 | |
1554 OLE_CALL_ARGS(priv->pCrossbar, get_PinCounts, &lOutputPins, &lInputPins); | |
1555 | |
1556 lInput = tv_available_inputs[input]; | |
1557 | |
1558 if (lInput < 0 || lInput >= lInputPins) | |
1559 return TVI_CONTROL_FALSE; | |
1560 | |
1561 OLE_CALL_ARGS(priv->pCrossbar, get_CrossbarPinInfo, 1 /* input */ , lInput, | |
1562 &lInputRelated, &lPhysicalType); | |
1563 | |
1564 nVideoDecoder = nAudioDecoder = -1; | |
1565 for (i = 0; i < lOutputPins; i++) { | |
1566 OLE_CALL_ARGS(priv->pCrossbar, get_CrossbarPinInfo, 0 /*output */ , i, | |
1567 &lRelated, &lPhysicalType); | |
1568 if (lPhysicalType == PhysConn_Video_VideoDecoder) | |
1569 nVideoDecoder = i; | |
1570 if (lPhysicalType == PhysConn_Audio_AudioDecoder) | |
1571 nAudioDecoder = i; | |
1572 } | |
1573 if (nVideoDecoder >= 0) { | |
1574 //connecting given input with video decoder | |
1575 hr = OLE_CALL_ARGS(priv->pCrossbar, Route, nVideoDecoder, lInput); | |
1576 if (hr != S_OK) { | |
1577 mp_msg(MSGT_TV,MSGL_ERR,MSGTR_TVI_DS_UnableConnectInputVideoDecoder, (unsigned int)hr); | |
1578 return TVI_CONTROL_FALSE; | |
1579 } | |
1580 } | |
1581 if (nAudioDecoder >= 0 && lInputRelated >= 0) { | |
1582 hr = OLE_CALL_ARGS(priv->pCrossbar, Route, nAudioDecoder, | |
1583 lInputRelated); | |
1584 if (hr != S_OK) { | |
1585 mp_msg(MSGT_TV,MSGL_ERR,MSGTR_TVI_DS_UnableConnectInputAudioDecoder, (unsigned int)hr); | |
1586 return TVI_CONTROL_FALSE; | |
1587 } | |
1588 } | |
1589 return TVI_CONTROL_TRUE; | |
1590 } | |
1591 | |
1592 /** | |
1593 * \brief adjusts video control (hue,saturation,contrast,brightess) | |
1594 * | |
1595 * \param priv driver's private data | |
1596 * \param control which control to adjust | |
1597 * \param value new value for control (0-100) | |
1598 * | |
1599 * \return TVI_CONTROL_TRUE success | |
1600 * \return TVI_CONTROL_FALSE error | |
1601 */ | |
1602 static int set_control(priv_t * priv, int control, int value) | |
1603 { | |
1604 long lMin, lMax, lStepping, lDefault, lFlags, lValue; | |
1605 HRESULT hr; | |
1606 | |
1607 mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: set_control called\n"); | |
1608 if (value < -100 || value > 100 || !priv->pVideoProcAmp) | |
1609 return TVI_CONTROL_FALSE; | |
1610 | |
1611 hr = OLE_CALL_ARGS(priv->pVideoProcAmp, GetRange, control, | |
1612 &lMin, &lMax, &lStepping, &lDefault, &lFlags); | |
1613 if (FAILED(hr) || lFlags != VideoProcAmp_Flags_Manual) | |
1614 return TVI_CONTROL_FALSE; | |
1615 | |
1616 lValue = lMin + (value + 100) * (lMax - lMin) / 200; | |
1617 /* | |
1618 Workaround for ATI AIW 7500. The driver reports: max=255, stepping=256 | |
1619 */ | |
1620 if (lStepping > lMax) { | |
1621 mp_msg(MSGT_TV, MSGL_DBG3, | |
1622 "tvi_dshow: Stepping (%ld) is bigger than max value (%ld) for control %d. Assuming 1\n", | |
1623 lStepping, lMax,control); | |
1624 lStepping = 1; | |
1625 } | |
1626 lValue -= lValue % lStepping; | |
1627 hr = OLE_CALL_ARGS(priv->pVideoProcAmp, Set, control, lValue, | |
1628 VideoProcAmp_Flags_Manual); | |
1629 if (FAILED(hr)) | |
1630 return TVI_CONTROL_FALSE; | |
1631 | |
1632 return TVI_CONTROL_TRUE; | |
1633 } | |
1634 | |
1635 /** | |
1636 * \brief get current value of video control (hue,saturation,contrast,brightess) | |
1637 * | |
1638 * \param priv driver's private data | |
1639 * \param control which control to adjust | |
1640 * \param pvalue address of variable thar receives current value | |
1641 * | |
1642 * \return TVI_CONTROL_TRUE success | |
1643 * \return TVI_CONTROL_FALSE error | |
1644 */ | |
1645 static int get_control(priv_t * priv, int control, int *pvalue) | |
1646 { | |
1647 long lMin, lMax, lStepping, lDefault, lFlags, lValue; | |
1648 HRESULT hr; | |
1649 | |
1650 mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: get_control called\n"); | |
1651 if (!pvalue || !priv->pVideoProcAmp) | |
1652 return TVI_CONTROL_FALSE; | |
1653 | |
1654 hr = OLE_CALL_ARGS(priv->pVideoProcAmp, GetRange, control, | |
1655 &lMin, &lMax, &lStepping, &lDefault, &lFlags); | |
1656 if (FAILED(hr)) | |
1657 return TVI_CONTROL_FALSE; | |
1658 if (lMin == lMax) { | |
1659 *pvalue = lMin; | |
1660 return TVI_CONTROL_TRUE; | |
1661 } | |
1662 | |
1663 hr = OLE_CALL_ARGS(priv->pVideoProcAmp, Get, control, &lValue, &lFlags); | |
1664 if (FAILED(hr)) | |
1665 return TVI_CONTROL_FALSE; | |
1666 | |
1667 *pvalue = 200 * (lValue - lMin) / (lMax - lMin) - 100; | |
1668 | |
1669 return TVI_CONTROL_TRUE; | |
1670 } | |
1671 | |
1672 /** | |
25053
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1673 * \brief create AM_MEDIA_TYPE structure, corresponding to given FourCC code and width/height/fps |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1674 * \param fcc FourCC code for video format |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1675 * \param width picture width |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1676 * \param height pciture height |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1677 * \param fps frames per second (required for bitrate calculation) |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1678 * |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1679 * \return pointer to AM_MEDIA_TYPE structure if success, NULL - otherwise |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1680 */ |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1681 static AM_MEDIA_TYPE* create_video_format(int fcc, int width, int height, int fps) |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1682 { |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1683 int i; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1684 AM_MEDIA_TYPE mt; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1685 VIDEOINFOHEADER vHdr; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1686 |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1687 /* Check given fcc in lookup table*/ |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1688 for(i=0; img_fmt_list[i].fmt && img_fmt_list[i].fmt!=fcc; i++) /* NOTHING */; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1689 if(!img_fmt_list[i].fmt) |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1690 return NULL; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1691 |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1692 memset(&mt, 0, sizeof(AM_MEDIA_TYPE)); |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1693 memset(&vHdr, 0, sizeof(VIDEOINFOHEADER)); |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1694 |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1695 vHdr.bmiHeader.biSize = sizeof(vHdr.bmiHeader); |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1696 vHdr.bmiHeader.biWidth = width; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1697 vHdr.bmiHeader.biHeight = height; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1698 //FIXME: is biPlanes required too? |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1699 //vHdr.bmiHeader.biPlanes = img_fmt_list[i].nPlanes; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1700 vHdr.bmiHeader.biBitCount = img_fmt_list[i].nBits; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1701 vHdr.bmiHeader.biCompression = img_fmt_list[i].nCompression; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1702 vHdr.bmiHeader.biSizeImage = width * height * img_fmt_list[i].nBits / 8; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1703 vHdr.dwBitRate = vHdr.bmiHeader.biSizeImage * 8 * fps; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1704 |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1705 mt.pbFormat = (char*)&vHdr; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1706 mt.cbFormat = sizeof(vHdr); |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1707 |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1708 mt.majortype = MEDIATYPE_Video; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1709 mt.subtype = *img_fmt_list[i].subtype; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1710 mt.formattype = FORMAT_VideoInfo; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1711 |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1712 mt.bFixedSizeSamples = 1; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1713 mt.bTemporalCompression = 0; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1714 mt.lSampleSize = vHdr.bmiHeader.biSizeImage; |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1715 |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1716 return CreateMediaType(&mt); |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1717 } |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1718 |
086c2accaaa2
Service routine for constructing AM_MEDIA_TYPE structure from
voroshil
parents:
25052
diff
changeset
|
1719 /** |
24744 | 1720 * \brief extracts fcc,width,height from AM_MEDIA_TYPE |
1721 * | |
1722 * \param pmt pointer to AM_MEDIA_TYPE to extract data from | |
1723 * \param pfcc address of variable that receives FourCC | |
1724 * \param pwidth address of variable that receives width | |
1725 * \param pheight address of variable that recevies height | |
1726 * | |
1727 * \return 1 if data extracted successfully, 0 - otherwise | |
1728 */ | |
1729 static int extract_video_format(AM_MEDIA_TYPE * pmt, int *pfcc, | |
1730 int *pwidth, int *pheight) | |
1731 { | |
1732 mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: extract_video_format called\n"); | |
1733 if (!pmt) | |
1734 return 0; | |
1735 if (!pmt->pbFormat) | |
1736 return 0; | |
1737 if (memcmp(&(pmt->formattype), &FORMAT_VideoInfo, 16) != 0) | |
1738 return 0; | |
1739 if (pfcc) | |
1740 *pfcc = subtype2imgfmt(&(pmt->subtype)); | |
1741 if (pwidth) | |
1742 *pwidth = ((VIDEOINFOHEADER *) pmt->pbFormat)->bmiHeader.biWidth; | |
1743 if (pheight) | |
1744 *pheight = ((VIDEOINFOHEADER *) pmt->pbFormat)->bmiHeader.biHeight; | |
1745 return 1; | |
1746 } | |
1747 | |
1748 /** | |
1749 * \brief extracts samplerate,bits,channels from AM_MEDIA_TYPE | |
1750 * | |
1751 * \param pmt pointer to AM_MEDIA_TYPE to extract data from | |
1752 * \param pfcc address of variable that receives samplerate | |
1753 * \param pwidth address of variable that receives number of bits per sample | |
1754 * \param pheight address of variable that recevies number of channels | |
1755 * | |
1756 * \return 1 if data extracted successfully, 0 - otherwise | |
1757 */ | |
1758 static int extract_audio_format(AM_MEDIA_TYPE * pmt, int *psamplerate, | |
1759 int *pbits, int *pchannels) | |
1760 { | |
1761 mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: extract_audio_format called\n"); | |
1762 if (!pmt) | |
1763 return 0; | |
1764 if (!pmt->pbFormat) | |
1765 return 0; | |
1766 if (memcmp(&(pmt->formattype), &FORMAT_WaveFormatEx, 16) != 0) | |
1767 return 0; | |
1768 if (psamplerate) | |
1769 *psamplerate = ((WAVEFORMATEX *) pmt->pbFormat)->nSamplesPerSec; | |
1770 if (pbits) | |
1771 *pbits = ((WAVEFORMATEX *) pmt->pbFormat)->wBitsPerSample; | |
1772 if (pchannels) | |
1773 *pchannels = ((WAVEFORMATEX *) pmt->pbFormat)->nChannels; | |
1774 return 1; | |
1775 } | |
1776 | |
1777 /** | |
1778 * \brief checks if AM_MEDIA_TYPE compatible with given samplerate,bits,channels | |
1779 * | |
1780 * \param pmt pointer to AM_MEDIA_TYPE for check | |
1781 * \param samplerate audio samplerate | |
1782 * \param bits bits per sample | |
1783 * \param channels number of audio channels | |
1784 * | |
1785 * \return 1 if AM_MEDIA_TYPE compatible | |
1786 * \return 0 if not | |
1787 */ | |
1788 static int check_audio_format(AM_MEDIA_TYPE * pmt, int samplerate, | |
1789 int bits, int channels) | |
1790 { | |
1791 mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: check_audio_format called\n"); | |
1792 if (!pmt) | |
1793 return 0; | |
1794 if (memcmp(&(pmt->majortype), &MEDIATYPE_Audio, 16) != 0) | |
1795 return 0; | |
1796 if (memcmp(&(pmt->subtype), &MEDIASUBTYPE_PCM, 16) != 0) | |
1797 return 0; | |
1798 if (memcmp(&(pmt->formattype), &FORMAT_WaveFormatEx, 16) != 0) | |
1799 return 0; | |
1800 if (!pmt->pbFormat) | |
1801 return 0; | |
1802 if (((WAVEFORMATEX *) pmt->pbFormat)->nSamplesPerSec != samplerate) | |
1803 return 0; | |
1804 if (((WAVEFORMATEX *) pmt->pbFormat)->wBitsPerSample != bits) | |
1805 return 0; | |
1806 if (channels > 0 | |
1807 && ((WAVEFORMATEX *) pmt->pbFormat)->nChannels != channels) | |
1808 return 0; | |
1809 | |
1810 return 1; | |
1811 } | |
1812 | |
1813 /** | |
1814 * \brief checks if AM_MEDIA_TYPE compatible with given fcc,width,height | |
1815 * | |
1816 * \param pmt pointer to AM_MEDIA_TYPE for check | |
1817 * \param fcc FourCC (compression) | |
1818 * \param width width of picture | |
1819 * \param height height of picture | |
1820 * | |
1821 * \return 1 if AM_MEDIA_TYPE compatible | |
1822 & \return 0 if not | |
1823 * | |
1824 * \note | |
1825 * width and height are currently not used | |
1826 * | |
1827 * \todo | |
1828 * add width/height check | |
1829 */ | |
1830 static int check_video_format(AM_MEDIA_TYPE * pmt, int fcc, int width, | |
1831 int height) | |
1832 { | |
1833 mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: check_video_format called\n"); | |
1834 if (!pmt) | |
1835 return 0; | |
1836 if (memcmp(&(pmt->majortype), &MEDIATYPE_Video, 16) != 0) | |
1837 return 0; | |
1838 if (subtype2imgfmt(&(pmt->subtype)) != fcc) | |
1839 return 0; | |
1840 return 1; | |
1841 } | |
1842 | |
1843 /** | |
1844 * \brief converts DirectShow subtype to MPlayer's IMGFMT | |
1845 * | |
1846 * \param subtype DirectShow subtype for video format | |
1847 * | |
1848 * \return MPlayer's IMGFMT or 0 if error occured | |
1849 */ | |
1850 static int subtype2imgfmt(const GUID * subtype) | |
1851 { | |
1852 int i; | |
1853 for (i = 0; img_fmt_list[i].fmt; i++) { | |
1854 if (memcmp(subtype, img_fmt_list[i].subtype, 16) == 0) | |
1855 return img_fmt_list[i].fmt; | |
1856 } | |
1857 return 0; | |
1858 } | |
1859 | |
1860 /** | |
1861 * \brief prints filter name and it pins | |
1862 * | |
1863 * \param pFilter - IBaseFilter to get data from | |
1864 * | |
1865 * \return S_OK if success, error code otherwise | |
1866 */ | |
1867 static HRESULT show_filter_info(IBaseFilter * pFilter) | |
1868 { | |
1869 char tmp[200]; | |
1870 FILTER_INFO fi; | |
1871 LPENUMPINS pEnum = 0; | |
1872 IPin *pPin = 0; | |
1873 PIN_DIRECTION ThisPinDir; | |
1874 PIN_INFO pi; | |
1875 HRESULT hr; | |
1876 int i; | |
1877 | |
1878 mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: show_filter_info called\n"); | |
1879 memset(&fi, 0, sizeof(fi)); | |
1880 memset(tmp, 0, 200); | |
1881 | |
1882 OLE_CALL_ARGS(pFilter, QueryFilterInfo, &fi); | |
1883 OLE_RELEASE_SAFE(fi.pGraph); | |
1884 wtoa(fi.achName, tmp, 200); | |
1885 mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: BaseFilter (%p): Name=%s, Graph=%p output pins:", | |
1886 pFilter, tmp, fi.pGraph); | |
1887 hr = OLE_CALL_ARGS(pFilter, EnumPins, &pEnum); | |
1888 if (FAILED(hr)) | |
1889 return hr; | |
1890 i = 0; | |
1891 while (OLE_CALL_ARGS(pEnum, Next, 1, &pPin, NULL) == S_OK) { | |
1892 memset(&pi, 0, sizeof(pi)); | |
1893 memset(tmp, 0, 200); | |
1894 OLE_CALL_ARGS(pPin, QueryDirection, &ThisPinDir); | |
1895 if (ThisPinDir == PINDIR_OUTPUT) { | |
1896 OLE_CALL_ARGS(pPin, QueryPinInfo, &pi); | |
1897 wtoa(pi.achName, tmp, 200); | |
1898 OLE_RELEASE_SAFE(pi.pFilter); | |
1899 mp_msg(MSGT_TV, MSGL_DBG2, " %d=%s", i, tmp); | |
1900 mp_msg(MSGT_TV, MSGL_DBG3, " (%p)", pPin); | |
1901 mp_msg(MSGT_TV, MSGL_DBG2, ";"); | |
1902 OLE_RELEASE_SAFE(pPin); | |
1903 i++; | |
1904 } | |
1905 } | |
1906 mp_msg(MSGT_TV, MSGL_DBG2, "\n"); | |
1907 OLE_RELEASE_SAFE(pEnum); | |
1908 return S_OK; | |
1909 } | |
1910 | |
1911 /** | |
1912 * \brief gets device's frendly in ANSI encoding | |
1913 * | |
1914 * \param pM IMoniker interface, got in enumeration process | |
1915 * \param category device category | |
1916 * | |
1917 * \return TVI_CONTROL_TRUE if operation succeded, TVI_CONTROL_FALSE - otherwise | |
1918 */ | |
1919 static int get_device_name(IMoniker * pM, char *pBuf, int nLen) | |
1920 { | |
1921 HRESULT hr; | |
1922 VARIANT var; | |
1923 IPropertyBag *pPropBag; | |
1924 hr = OLE_CALL_ARGS(pM, BindToStorage, 0, 0, &IID_IPropertyBag,(void *) &pPropBag); | |
1925 if (FAILED(hr)) { | |
1926 mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Call to BindToStorage failed\n"); | |
1927 return TVI_CONTROL_FALSE; | |
1928 } | |
1929 var.vt = VT_BSTR; | |
1930 hr = OLE_CALL_ARGS(pPropBag, Read, L"Description", (LPVARIANT) & var, | |
1931 NULL); | |
1932 if (FAILED(hr)) { | |
1933 hr = OLE_CALL_ARGS(pPropBag, Read, L"FriendlyName", (LPVARIANT) & var, | |
1934 NULL); | |
1935 } | |
1936 OLE_RELEASE_SAFE(pPropBag); | |
1937 if (SUCCEEDED(hr)) { | |
1938 wtoa(var.bstrVal, pBuf, nLen); | |
1939 return TVI_CONTROL_TRUE; | |
1940 } | |
1941 return TVI_CONTROL_FALSE; | |
1942 } | |
1943 | |
1944 /** | |
1945 * \brief find capture device at given index | |
1946 * | |
1947 * \param index device index to search for (-1 mean only print available) | |
1948 * \param category device category | |
1949 * | |
1950 * \return IBaseFilter interface for capture device with given index | |
1951 * | |
1952 * Sample values for category: | |
1953 * CLSID_VideoInputDeviceCategory - Video Capture Sources | |
1954 * CLSID_AudioInputDeviceCategory - Audio Capture Sources | |
1955 * See DirectShow SDK documentation for other possible values | |
1956 */ | |
1957 static IBaseFilter *find_capture_device(int index, REFCLSID category) | |
1958 { | |
1959 IBaseFilter *pFilter = NULL; | |
1960 ICreateDevEnum *pDevEnum = NULL; | |
1961 IEnumMoniker *pClassEnum = NULL; | |
1962 IMoniker *pM; | |
1963 HRESULT hr; | |
1964 ULONG cFetched; | |
1965 int i; | |
1966 char tmp[DEVICE_NAME_MAX_LEN + 1]; | |
1967 hr = CoCreateInstance((GUID *) & CLSID_SystemDeviceEnum, NULL, | |
1968 CLSCTX_INPROC_SERVER, &IID_ICreateDevEnum, | |
1969 (void *) &pDevEnum); | |
1970 if (FAILED(hr)) { | |
1971 mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Unable to create device enumerator\n"); | |
1972 return NULL; | |
1973 } | |
1974 | |
1975 hr = OLE_CALL_ARGS(pDevEnum, CreateClassEnumerator, category, &pClassEnum, 0); | |
1976 OLE_RELEASE_SAFE(pDevEnum); | |
1977 if (FAILED(hr)) { | |
1978 mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Unable to create class enumerator\n"); | |
1979 return NULL; | |
1980 } | |
1981 if (hr == S_FALSE) { | |
1982 mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: No capture devices found\n"); | |
1983 return NULL; | |
1984 } | |
1985 | |
1986 OLE_CALL(pClassEnum,Reset); | |
1987 for (i = 0; OLE_CALL_ARGS(pClassEnum, Next, 1, &pM, &cFetched) == S_OK; i++) { | |
1988 if(get_device_name(pM, tmp, DEVICE_NAME_MAX_LEN)!=TVI_CONTROL_TRUE) | |
1989 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TVI_DS_UnableGetDeviceName, i); | |
1990 else | |
1991 mp_msg(MSGT_TV, MSGL_V, MSGTR_TVI_DS_DeviceName, i, tmp); | |
1992 if (index != -1 && i == index) { | |
1993 mp_msg(MSGT_TV, MSGL_INFO, MSGTR_TVI_DS_UsingDevice, index, tmp); | |
1994 hr = OLE_CALL_ARGS(pM, BindToObject, 0, 0, &IID_IBaseFilter,(void *) &pFilter); | |
1995 if (FAILED(hr)) | |
1996 pFilter = NULL; | |
1997 } | |
1998 OLE_RELEASE_SAFE(pM); | |
1999 } | |
2000 if (index != -1 && !pFilter) { | |
2001 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TVI_DS_DeviceNotFound, | |
2002 index); | |
2003 } | |
2004 OLE_RELEASE_SAFE(pClassEnum); | |
2005 | |
2006 return pFilter; | |
2007 } | |
2008 | |
2009 /** | |
2010 * \brief get array of available formats through call to IAMStreamConfig::GetStreamCaps | |
25088
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2011 * |
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2012 * \praram[in] chain chain data structure |
24744 | 2013 * |
2014 * \return S_OK success | |
2015 * \return E_POINTER one of parameters is NULL | |
2016 * \return E_FAIL required size of buffer is unknown for given media type | |
2017 * \return E_OUTOFMEMORY not enough memory | |
2018 * \return other error code from called methods | |
2019 * | |
2020 * \remarks | |
25088
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2021 * last items of chain->arpmt and chain->arStreamCaps will be NULL |
24744 | 2022 */ |
25088
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2023 static HRESULT get_available_formats_stream(chain_t *chain) |
24744 | 2024 { |
2025 AM_MEDIA_TYPE **arpmt; | |
2026 void **pBuf=NULL; | |
2027 | |
2028 HRESULT hr; | |
2029 int i, count, size; | |
2030 int done; | |
2031 | |
2032 mp_msg(MSGT_TV, MSGL_DBG4, | |
2033 "tvi_dshow: get_available_formats_stream called\n"); | |
2034 | |
25090 | 2035 if (!chain->pStreamConfig) |
24744 | 2036 return E_POINTER; |
2037 | |
25088
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2038 hr=OLE_CALL_ARGS(chain->pStreamConfig, GetNumberOfCapabilities, &count, &size); |
24744 | 2039 if (FAILED(hr)) { |
2040 mp_msg(MSGT_TV, MSGL_DBG4, | |
2041 "tvi_dshow: Call to GetNumberOfCapabilities failed (get_available_formats_stream)\n"); | |
2042 return hr; | |
2043 } | |
25088
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2044 if (chain->type == video){ |
24744 | 2045 if (size != sizeof(VIDEO_STREAM_CONFIG_CAPS)) { |
2046 mp_msg(MSGT_TV, MSGL_DBG4, | |
2047 "tvi_dshow: Wrong video structure size for GetNumberOfCapabilities (get_available_formats_stream)\n"); | |
2048 return E_FAIL; | |
25089
791f867d0124
Fix totally wrong (due to mess of brackets) structures size check.
voroshil
parents:
25088
diff
changeset
|
2049 } |
791f867d0124
Fix totally wrong (due to mess of brackets) structures size check.
voroshil
parents:
25088
diff
changeset
|
2050 } else if (chain->type == audio){ |
791f867d0124
Fix totally wrong (due to mess of brackets) structures size check.
voroshil
parents:
25088
diff
changeset
|
2051 if (size != sizeof(AUDIO_STREAM_CONFIG_CAPS)) { |
791f867d0124
Fix totally wrong (due to mess of brackets) structures size check.
voroshil
parents:
25088
diff
changeset
|
2052 mp_msg(MSGT_TV, MSGL_DBG4, |
24744 | 2053 "tvi_dshow: Wrong audio structure size for GetNumberOfCapabilities (get_available_formats_stream)\n"); |
25089
791f867d0124
Fix totally wrong (due to mess of brackets) structures size check.
voroshil
parents:
25088
diff
changeset
|
2054 return E_FAIL; |
791f867d0124
Fix totally wrong (due to mess of brackets) structures size check.
voroshil
parents:
25088
diff
changeset
|
2055 } |
791f867d0124
Fix totally wrong (due to mess of brackets) structures size check.
voroshil
parents:
25088
diff
changeset
|
2056 } else { |
24744 | 2057 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TVI_DS_UnsupportedMediaType,"get_available_formats_stream"); |
2058 return E_FAIL; | |
2059 } | |
2060 done = 0; | |
2061 | |
2062 arpmt = (AM_MEDIA_TYPE **) malloc((count + 1) * sizeof(AM_MEDIA_TYPE *)); | |
2063 if (arpmt) { | |
2064 memset(arpmt, 0, (count + 1) * sizeof(AM_MEDIA_TYPE *)); | |
2065 | |
2066 pBuf = (void **) malloc((count + 1) * sizeof(void *)); | |
2067 if (pBuf) { | |
2068 memset(pBuf, 0, (count + 1) * sizeof(void *)); | |
2069 | |
2070 for (i = 0; i < count; i++) { | |
25127
6e039dd0b5d8
Revert r25089 (Ignore video formats which are supported by device
voroshil
parents:
25126
diff
changeset
|
2071 pBuf[i] = malloc(size); |
6e039dd0b5d8
Revert r25089 (Ignore video formats which are supported by device
voroshil
parents:
25126
diff
changeset
|
2072 |
6e039dd0b5d8
Revert r25089 (Ignore video formats which are supported by device
voroshil
parents:
25126
diff
changeset
|
2073 if (!pBuf[i]) |
24744 | 2074 break; |
2075 | |
25088
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2076 hr = OLE_CALL_ARGS(chain->pStreamConfig, GetStreamCaps, i, |
25127
6e039dd0b5d8
Revert r25089 (Ignore video formats which are supported by device
voroshil
parents:
25126
diff
changeset
|
2077 &(arpmt[i]), pBuf[i]); |
24744 | 2078 if (FAILED(hr)) |
2079 break; | |
2080 } | |
2081 if (i == count) { | |
25088
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2082 chain->arpmt = arpmt; |
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2083 chain->arStreamCaps = pBuf; |
24744 | 2084 done = 1; |
2085 } | |
2086 } | |
2087 } | |
2088 if (!done) { | |
2089 for (i = 0; i < count; i++) { | |
2090 if (pBuf && pBuf[i]) | |
2091 free(pBuf[i]); | |
2092 if (arpmt && arpmt[i]) | |
2093 DeleteMediaType(arpmt[i]); | |
2094 } | |
2095 if (pBuf) | |
2096 free(pBuf); | |
2097 if (arpmt) | |
2098 free(arpmt); | |
2099 if (hr != S_OK) { | |
2100 mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: Call to GetStreamCaps failed (get_available_formats_stream)\n"); | |
2101 return hr; | |
2102 } else | |
2103 return E_OUTOFMEMORY; | |
2104 } | |
2105 return S_OK; | |
2106 } | |
2107 | |
2108 /** | |
2109 * \brief returns allocates an array and store available media formats for given pin type to it | |
2110 * | |
2111 * \param pBuilder ICaptureGraphBuilder2 interface of graph builder | |
25088
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2112 * \param chain chain data structure |
24744 | 2113 * |
2114 * \return S_OK success | |
2115 * \return E_POINTER one of given pointers is null | |
2116 * \return apropriate error code otherwise | |
2117 */ | |
2118 static HRESULT get_available_formats_pin(ICaptureGraphBuilder2 * pBuilder, | |
25088
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2119 chain_t *chain) |
24744 | 2120 { |
2121 IEnumMediaTypes *pEnum; | |
2122 int i, count, size; | |
2123 ULONG cFetched; | |
2124 AM_MEDIA_TYPE *pmt; | |
2125 HRESULT hr; | |
2126 void **pBuf; | |
2127 AM_MEDIA_TYPE **arpmt; //This will be real array | |
2128 VIDEO_STREAM_CONFIG_CAPS *pVideoCaps; | |
2129 AUDIO_STREAM_CONFIG_CAPS *pAudioCaps; | |
2130 int p1, p2, p3; | |
2131 | |
2132 mp_msg(MSGT_TV, MSGL_DBG4, | |
2133 "tvi_dshow: get_available_formats_pin called\n"); | |
25088
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2134 if (!pBuilder || !chain->pCaptureFilter) |
24744 | 2135 return E_POINTER; |
2136 | |
25093 | 2137 if (!chain->pCapturePin) |
2138 { | |
2139 hr = OLE_CALL_ARGS(pBuilder, FindPin, | |
2140 (IUnknown *) chain->pCaptureFilter, | |
2141 PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, | |
2142 chain->majortype, FALSE, 0, &chain->pCapturePin); | |
2143 | |
2144 if (!chain->pCapturePin) | |
2145 return E_POINTER; | |
2146 } | |
25088
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2147 if (chain->type == video) { |
24744 | 2148 size = sizeof(VIDEO_STREAM_CONFIG_CAPS); |
25088
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2149 } else if (chain->type == audio) { |
24744 | 2150 size = sizeof(AUDIO_STREAM_CONFIG_CAPS); |
2151 } else { | |
2152 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TVI_DS_UnsupportedMediaType,"get_available_formats_pin"); | |
2153 return E_FAIL; | |
2154 } | |
2155 | |
25088
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2156 hr = OLE_CALL_ARGS(chain->pCapturePin, EnumMediaTypes, &pEnum); |
24744 | 2157 if (FAILED(hr)) { |
2158 mp_msg(MSGT_TV, MSGL_DBG4, | |
2159 "tvi_dshow: Call to EnumMediaTypes failed (get_available_formats_pin)\n"); | |
2160 return hr; | |
2161 } | |
2162 for (i = 0; OLE_CALL_ARGS(pEnum, Next, 1, &pmt, &cFetched) == S_OK; i++) { | |
2163 if (!pmt) | |
2164 break; | |
2165 } | |
2166 OLE_CALL(pEnum,Reset); | |
2167 | |
2168 count = i; | |
2169 arpmt = | |
2170 (AM_MEDIA_TYPE **) malloc((count + 1) * sizeof(AM_MEDIA_TYPE *)); | |
2171 if (!arpmt) | |
2172 return E_OUTOFMEMORY; | |
2173 memset(arpmt, 0, (count + 1) * sizeof(AM_MEDIA_TYPE *)); | |
2174 | |
2175 for (i = 0; | |
2176 i < count | |
2177 && OLE_CALL_ARGS(pEnum, Next, 1, &(arpmt[i]), &cFetched) == S_OK; | |
2178 i++); | |
2179 | |
2180 OLE_RELEASE_SAFE(pEnum); | |
2181 | |
2182 | |
2183 pBuf = (void **) malloc((count + 1) * sizeof(void *)); | |
2184 if (!pBuf) { | |
2185 for (i = 0; i < count; i++) | |
2186 if (arpmt[i]) | |
2187 DeleteMediaType(arpmt[i]); | |
2188 free(arpmt); | |
2189 return E_OUTOFMEMORY; | |
2190 } | |
2191 memset(pBuf, 0, (count + 1) * sizeof(void *)); | |
2192 | |
2193 for (i = 0; i < count; i++) { | |
2194 pBuf[i] = malloc(size); | |
2195 if (!pBuf[i]) | |
2196 break; | |
2197 memset(pBuf[i], 0, size); | |
2198 | |
25088
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2199 if (chain->type == video) { |
24744 | 2200 pVideoCaps = (VIDEO_STREAM_CONFIG_CAPS *) pBuf[i]; |
2201 extract_video_format(arpmt[i], NULL, &p1, &p2); | |
2202 pVideoCaps->MaxOutputSize.cx = pVideoCaps->MinOutputSize.cx = | |
2203 p1; | |
2204 pVideoCaps->MaxOutputSize.cy = pVideoCaps->MinOutputSize.cy = | |
2205 p2; | |
2206 } else { | |
2207 pAudioCaps = (AUDIO_STREAM_CONFIG_CAPS *) pBuf[i]; | |
2208 extract_audio_format(arpmt[i], &p1, &p2, &p3); | |
2209 pAudioCaps->MaximumSampleFrequency = | |
2210 pAudioCaps->MinimumSampleFrequency = p1; | |
2211 pAudioCaps->MaximumBitsPerSample = | |
2212 pAudioCaps->MinimumBitsPerSample = p2; | |
2213 pAudioCaps->MaximumChannels = pAudioCaps->MinimumChannels = p3; | |
2214 } | |
2215 | |
2216 } | |
2217 if (i != count) { | |
2218 for (i = 0; i < count; i++) { | |
2219 if (arpmt[i]) | |
2220 DeleteMediaType(arpmt[i]); | |
2221 if (pBuf[i]) | |
2222 free(pBuf[i]); | |
2223 } | |
2224 free(arpmt); | |
2225 free(pBuf); | |
2226 return E_OUTOFMEMORY; | |
2227 } | |
25088
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2228 chain->arpmt = arpmt; |
554bbb45a2f2
Replace several parameters for get_available_formats_stream
voroshil
parents:
25087
diff
changeset
|
2229 chain->arStreamCaps = pBuf; |
24744 | 2230 |
2231 return S_OK; | |
2232 } | |
2233 | |
2234 /* | |
2235 *--------------------------------------------------------------------------------------- | |
2236 * | |
2237 * Public methods | |
2238 * | |
2239 *--------------------------------------------------------------------------------------- | |
2240 */ | |
2241 /** | |
2242 * \brief fills given buffer with audio data (usually one block) | |
2243 * | |
2244 * \param priv driver's private data structure | |
2245 * \param buffer buffer to store data to | |
2246 * \param len buffer's size in bytes (usually one block size) | |
2247 * | |
2248 * \return audio pts if audio present, 1 - otherwise | |
2249 */ | |
2250 static double grab_audio_frame(priv_t * priv, char *buffer, int len) | |
2251 { | |
2252 int bytes = 0; | |
2253 int i; | |
2254 double pts; | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2255 grabber_ringbuffer_t *rb = priv->chains[1]->rbuf; |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2256 grabber_ringbuffer_t *vrb = priv->chains[0]->rbuf; |
24744 | 2257 |
2258 if (!rb || !rb->ringbuffer) | |
2259 return 1; | |
2260 | |
2261 if(vrb && vrb->tStart<0){ | |
2262 memset(buffer,0,len); | |
2263 return 0; | |
2264 } | |
2265 if(vrb && rb->tStart<0) | |
2266 rb->tStart=vrb->tStart; | |
2267 | |
2268 if (len < rb->blocksize) | |
2269 bytes = len; | |
2270 else | |
2271 bytes = rb->blocksize; | |
2272 | |
2273 mp_msg(MSGT_TV, MSGL_DBG3,"tvi_dshow: FillBuffer (audio) called. %d blocks in buffer, %d bytes requested\n", | |
2274 rb->count, len); | |
2275 if(!rb->count){ | |
2276 mp_msg(MSGT_TV,MSGL_DBG4,"tvi_dshow: waiting for frame\n"); | |
2277 for(i=0;i<1000 && !rb->count;i++) usec_sleep(1000); | |
2278 if(!rb->count){ | |
2279 mp_msg(MSGT_TV,MSGL_DBG4,"tvi_dshow: waiting timeout\n"); | |
2280 return 0; | |
2281 } | |
2282 mp_msg(MSGT_TV,MSGL_DBG4,"tvi_dshow: got frame!\n"); | |
2283 } | |
2284 | |
2285 EnterCriticalSection(rb->pMutex); | |
2286 pts=rb->dpts[rb->head]-rb->tStart; | |
2287 memcpy(buffer, rb->ringbuffer[rb->head], bytes); | |
2288 rb->head = (rb->head + 1) % rb->buffersize; | |
2289 rb->count--; | |
2290 LeaveCriticalSection(rb->pMutex); | |
2291 return pts; | |
2292 } | |
2293 | |
2294 /** | |
2295 * \brief returns audio frame size | |
2296 * | |
2297 * \param priv driver's private data structure | |
2298 * | |
2299 * \return audio block size if audio enabled and 1 - otherwise | |
2300 */ | |
2301 static int get_audio_framesize(priv_t * priv) | |
2302 { | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2303 if (!priv->chains[1]->rbuf) |
24744 | 2304 return 1; //no audio |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2305 mp_msg(MSGT_TV,MSGL_DBG3,"get_audio_framesize: %d\n",priv->chains[1]->rbuf->blocksize); |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2306 return priv->chains[1]->rbuf->blocksize; |
24744 | 2307 } |
2308 | |
27370
14c5017f40d2
Change a bunch of video/audio-output-specific preprocessor directives from
diego
parents:
26756
diff
changeset
|
2309 #ifdef CONFIG_TV_TELETEXT |
24744 | 2310 static int vbi_get_props(priv_t* priv,tt_stream_props* ptsp) |
2311 { | |
2312 if(!priv || !ptsp) | |
2313 return TVI_CONTROL_FALSE; | |
2314 | |
2315 //STUBS!!! | |
2316 ptsp->interlaced=0; | |
2317 ptsp->offset=256; | |
2318 | |
2319 ptsp->sampling_rate=27e6; | |
2320 ptsp->samples_per_line=720; | |
2321 | |
2322 ptsp->count[0]=16; | |
2323 ptsp->count[1]=16; | |
2324 //END STUBS!!! | |
2325 ptsp->bufsize = ptsp->samples_per_line * (ptsp->count[0] + ptsp->count[1]); | |
2326 | |
2327 mp_msg(MSGT_TV,MSGL_V,"vbi_get_props: sampling_rate=%d,offset:%d,samples_per_line: %d\n interlaced:%s, count=[%d,%d]\n", | |
2328 ptsp->sampling_rate, | |
2329 ptsp->offset, | |
2330 ptsp->samples_per_line, | |
2331 ptsp->interlaced?"Yes":"No", | |
2332 ptsp->count[0], | |
2333 ptsp->count[1]); | |
2334 | |
2335 return TVI_CONTROL_TRUE; | |
2336 } | |
2337 | |
2338 static void vbi_grabber(priv_t* priv) | |
2339 { | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2340 grabber_ringbuffer_t *rb = priv->chains[2]->rbuf; |
24744 | 2341 int i; |
2342 unsigned char* buf; | |
2343 if (!rb || !rb->ringbuffer) | |
2344 return; | |
2345 | |
2346 buf=calloc(1,rb->blocksize); | |
2347 for(i=0; i<23 && rb->count; i++){ | |
2348 memcpy(buf,rb->ringbuffer[rb->head],rb->blocksize); | |
2349 teletext_control(priv->priv_vbi,TV_VBI_CONTROL_DECODE_PAGE,&buf); | |
2350 rb->head = (rb->head + 1) % rb->buffersize; | |
2351 rb->count--; | |
2352 } | |
2353 free(buf); | |
2354 } | |
27370
14c5017f40d2
Change a bunch of video/audio-output-specific preprocessor directives from
diego
parents:
26756
diff
changeset
|
2355 #endif /* CONFIG_TV_TELETEXT */ |
24744 | 2356 |
2357 /** | |
2358 * \brief fills given buffer with video data (usually one frame) | |
2359 * | |
2360 * \param priv driver's private data structure | |
2361 * \param buffer buffer to store data to | |
2362 * \param len buffer's size in bytes (usually one frame size) | |
2363 * | |
2364 * \return frame size if video present, 0 - otherwise | |
2365 */ | |
2366 static double grab_video_frame(priv_t * priv, char *buffer, int len) | |
2367 { | |
2368 int bytes = 0; | |
2369 int i; | |
2370 double pts; | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2371 grabber_ringbuffer_t *rb = priv->chains[0]->rbuf; |
24744 | 2372 |
2373 if (!rb || !rb->ringbuffer) | |
2374 return 1; | |
2375 if (len < rb->blocksize) | |
2376 bytes = len; | |
2377 else | |
2378 bytes = rb->blocksize; | |
2379 | |
2380 mp_msg(MSGT_TV, MSGL_DBG3,"tvi_dshow: FillBuffer (video) called. %d blocks in buffer, %d bytes requested\n", | |
2381 rb->count, len); | |
2382 if(!rb->count){ | |
2383 mp_msg(MSGT_TV,MSGL_DBG4,"tvi_dshow: waiting for frame\n"); | |
2384 for(i=0;i<1000 && !rb->count;i++) usec_sleep(1000); | |
2385 if(!rb->count){ | |
2386 mp_msg(MSGT_TV,MSGL_DBG4,"tvi_dshow: waiting timeout\n"); | |
2387 return 0; | |
2388 } | |
2389 mp_msg(MSGT_TV,MSGL_DBG4,"tvi_dshow: got frame!\n"); | |
2390 } | |
2391 EnterCriticalSection(rb->pMutex); | |
2392 if(rb->tStart<0) | |
2393 rb->tStart=rb->dpts[rb->head]; | |
2394 pts=rb->dpts[rb->head]-rb->tStart; | |
2395 memcpy(buffer, rb->ringbuffer[rb->head], bytes); | |
2396 rb->head = (rb->head + 1) % rb->buffersize; | |
2397 rb->count--; | |
2398 LeaveCriticalSection(rb->pMutex); | |
2399 | |
27370
14c5017f40d2
Change a bunch of video/audio-output-specific preprocessor directives from
diego
parents:
26756
diff
changeset
|
2400 #ifdef CONFIG_TV_TELETEXT |
24744 | 2401 vbi_grabber(priv); |
2402 #endif | |
2403 return pts; | |
2404 } | |
2405 | |
2406 /** | |
2407 * \brief returns frame size | |
2408 * | |
2409 * \param priv driver's private data structure | |
2410 * | |
2411 * \return frame size if video present, 0 - otherwise | |
2412 */ | |
2413 static int get_video_framesize(priv_t * priv) | |
2414 { | |
2415 // if(!priv->pmtVideo) return 1; //no video | |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
2416 // return priv->pmtVideo->lSampleSize; |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2417 if (!priv->chains[0]->rbuf) |
24744 | 2418 return 1; //no video |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2419 mp_msg(MSGT_TV,MSGL_DBG3,"geT_video_framesize: %d\n",priv->chains[0]->rbuf->blocksize); |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2420 return priv->chains[0]->rbuf->blocksize; |
24744 | 2421 } |
2422 | |
2423 /** | |
2424 * \brief calculate audio buffer size | |
2425 * \param video_buf_size size of video buffer in bytes | |
2426 * \param video_bitrate video bit rate | |
2427 * \param audio_bitrate audio bit rate | |
2428 * \return audio buffer isze in bytes | |
2429 * | |
2430 * \remarks length of video buffer and resulted audio buffer calculated in | |
2431 * seconds will be the same. | |
2432 */ | |
2433 static inline int audio_buf_size_from_video(int video_buf_size, int video_bitrate, int audio_bitrate) | |
2434 { | |
2435 int audio_buf_size = audio_bitrate * (video_buf_size / video_bitrate); | |
2436 mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: Audio capture buffer: %d * %d / %d = %d\n", | |
2437 audio_bitrate,video_buf_size,video_bitrate,audio_buf_size); | |
2438 return audio_buf_size; | |
2439 } | |
2440 | |
2441 /** | |
25094
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2442 * \brief common chain initialization routine |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2443 * \param chain chain data structure |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2444 * |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2445 * \note pCaptureFilter member should be initialized before call to this routine |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2446 */ |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2447 static HRESULT init_chain_common(ICaptureGraphBuilder2 *pBuilder, chain_t *chain) |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2448 { |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2449 HRESULT hr; |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2450 int i; |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2451 |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2452 if(!chain->pCaptureFilter) |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2453 return E_POINTER; |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2454 |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2455 show_filter_info(chain->pCaptureFilter); |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2456 |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2457 hr = OLE_CALL_ARGS(pBuilder, FindPin, |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2458 (IUnknown *) chain->pCaptureFilter, |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2459 PINDIR_OUTPUT, chain->pin_category, |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2460 chain->majortype, FALSE, 0, &chain->pCapturePin); |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2461 |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2462 if (FAILED(hr)) { |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2463 mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: FindPin(pCapturePin) call failed. Error:0x%x\n", (unsigned int)hr); |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2464 return hr; |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2465 } |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2466 |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2467 hr = OLE_CALL_ARGS(pBuilder, FindInterface, |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2468 chain->pin_category, |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2469 chain->majortype, |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2470 chain->pCaptureFilter, |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2471 &IID_IAMStreamConfig, |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2472 (void **) &(chain->pStreamConfig)); |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2473 if (FAILED(hr)) |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2474 chain->pStreamConfig = NULL; |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2475 |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2476 /* |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2477 Getting available video formats (last pointer in array will be NULL) |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2478 First tryin to call IAMStreamConfig::GetStreamCaos. this will give us additional information such as |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2479 min/max picture dimensions, etc. If this call fails trying IPIn::EnumMediaTypes with default |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2480 min/max values. |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2481 */ |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2482 hr = get_available_formats_stream(chain); |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2483 if (FAILED(hr)) { |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2484 mp_msg(MSGT_TV, MSGL_DBG2, "Unable to use IAMStreamConfig for retriving available formats (Error:0x%x). Using EnumMediaTypes instead\n", (unsigned int)hr); |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2485 hr = get_available_formats_pin(pBuilder, chain); |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2486 if(FAILED(hr)){ |
25125
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2487 return hr; |
25094
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2488 } |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2489 } |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2490 chain->nFormatUsed = 0; |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2491 |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2492 //If argument to CreateMediaType is NULL then result will be NULL too. |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2493 chain->pmt = CreateMediaType(chain->arpmt[0]); |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2494 |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2495 for (i = 0; chain->arpmt[i]; i++) |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2496 DisplayMediaType("Available format", chain->arpmt[i]); |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2497 |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2498 return S_OK; |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2499 } |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2500 /** |
25057
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2501 * \brief build video stream chain in graph |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2502 * \param priv private data structure |
24744 | 2503 * |
25057
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2504 * \return S_OK if chain was built successfully, apropriate error code otherwise |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2505 */ |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2506 static HRESULT build_video_chain(priv_t *priv) |
24744 | 2507 { |
2508 HRESULT hr; | |
2509 | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2510 if(priv->chains[0]->rbuf) |
25059 | 2511 return S_OK; |
2512 | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2513 if (priv->chains[0]->pStreamConfig) { |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2514 hr = OLE_CALL_ARGS(priv->chains[0]->pStreamConfig, SetFormat, priv->chains[0]->pmt); |
24744 | 2515 if (FAILED(hr)) { |
2516 mp_msg(MSGT_TV,MSGL_ERR,MSGTR_TVI_DS_UnableSelectVideoFormat, (unsigned int)hr); | |
2517 } | |
2518 } | |
2519 | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2520 priv->chains[0]->rbuf=calloc(1,sizeof(grabber_ringbuffer_t)); |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2521 if(!priv->chains[0]->rbuf) |
25058 | 2522 return E_OUTOFMEMORY; |
24744 | 2523 |
2524 if (priv->tv_param->buffer_size >= 0) { | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2525 priv->chains[0]->rbuf->buffersize = priv->tv_param->buffer_size; |
24744 | 2526 } else { |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2527 priv->chains[0]->rbuf->buffersize = 16; |
24744 | 2528 } |
2529 | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2530 priv->chains[0]->rbuf->buffersize *= 1024 * 1024; |
25084
f72ebba1e6d1
pass chain structure instead of several variables to build_sub_graph
voroshil
parents:
25083
diff
changeset
|
2531 hr=build_sub_graph(priv, priv->chains[0], &PIN_CATEGORY_CAPTURE); |
24744 | 2532 if(FAILED(hr)){ |
2533 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TVI_DS_UnableBuildVideoSubGraph,(unsigned int)hr); | |
25057
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2534 return hr; |
24744 | 2535 } |
25057
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2536 return S_OK; |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2537 } |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2538 |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2539 /** |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2540 * \brief build audio stream chain in graph |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2541 * \param priv private data structure |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2542 * |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2543 * \return S_OK if chain was built successfully, apropriate error code otherwise |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2544 */ |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2545 static HRESULT build_audio_chain(priv_t *priv) |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2546 { |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2547 HRESULT hr; |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2548 |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2549 if(priv->chains[1]->rbuf) |
25059 | 2550 return S_OK; |
2551 | |
25057
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2552 if(priv->immediate_mode) |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2553 return S_OK; |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2554 |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2555 if (priv->chains[1]->pStreamConfig) { |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2556 hr = OLE_CALL_ARGS(priv->chains[1]->pStreamConfig, SetFormat, |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2557 priv->chains[1]->pmt); |
25057
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2558 if (FAILED(hr)) { |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2559 mp_msg(MSGT_TV,MSGL_ERR,MSGTR_TVI_DS_UnableSelectAudioFormat, (unsigned int)hr); |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2560 } |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2561 } |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2562 |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2563 if(priv->chains[1]->pmt){ |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2564 priv->chains[1]->rbuf=calloc(1,sizeof(grabber_ringbuffer_t)); |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2565 if(!priv->chains[1]->rbuf) |
25058 | 2566 return E_OUTOFMEMORY; |
24744 | 2567 |
2568 /* let the audio buffer be the same size (in seconds) than video one */ | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2569 priv->chains[1]->rbuf->buffersize=audio_buf_size_from_video( |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2570 priv->chains[0]->rbuf->buffersize, |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2571 (((VIDEOINFOHEADER *) priv->chains[0]->pmt->pbFormat)->dwBitRate), |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2572 (((WAVEFORMATEX *) (priv->chains[1]->pmt->pbFormat))->nAvgBytesPerSec)); |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2573 |
25084
f72ebba1e6d1
pass chain structure instead of several variables to build_sub_graph
voroshil
parents:
25083
diff
changeset
|
2574 hr=build_sub_graph(priv, priv->chains[1],&PIN_CATEGORY_CAPTURE); |
24744 | 2575 if(FAILED(hr)){ |
2576 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TVI_DS_UnableBuildAudioSubGraph,(unsigned int)hr); | |
2577 return 0; | |
2578 } | |
2579 } | |
25057
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2580 return S_OK; |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2581 } |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2582 |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2583 /** |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2584 * \brief build VBI stream chain in graph |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2585 * \param priv private data structure |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2586 * |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2587 * \return S_OK if chain was built successfully, apropriate error code otherwise |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2588 */ |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2589 static HRESULT build_vbi_chain(priv_t *priv) |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2590 { |
27370
14c5017f40d2
Change a bunch of video/audio-output-specific preprocessor directives from
diego
parents:
26756
diff
changeset
|
2591 #ifdef CONFIG_TV_TELETEXT |
25057
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2592 HRESULT hr; |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2593 |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2594 if(priv->chains[2]->rbuf) |
25059 | 2595 return S_OK; |
2596 | |
24744 | 2597 if(priv->tv_param->tdevice) |
2598 { | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2599 priv->chains[2]->rbuf=calloc(1,sizeof(grabber_ringbuffer_t)); |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2600 if(!priv->chains[2]->rbuf) |
25058 | 2601 return E_OUTOFMEMORY; |
2602 | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2603 init_ringbuffer(priv->chains[2]->rbuf,24,priv->tsp.bufsize); |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2604 |
25084
f72ebba1e6d1
pass chain structure instead of several variables to build_sub_graph
voroshil
parents:
25083
diff
changeset
|
2605 hr=build_sub_graph(priv, priv->chains[2],&PIN_CATEGORY_VBI); |
24744 | 2606 if(FAILED(hr)){ |
2607 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TVI_DS_UnableBuildVBISubGraph,(unsigned int)hr); | |
2608 return 0; | |
2609 } | |
2610 } | |
2611 #endif | |
25057
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2612 return S_OK; |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2613 } |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2614 |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2615 /** |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2616 * \brief playback/capture real start |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2617 * |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2618 * \param priv driver's private data structure |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2619 * |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2620 * \return 1 if success, 0 - otherwise |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2621 * |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2622 * TODO: move some code from init() here |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2623 */ |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2624 static int start(priv_t * priv) |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2625 { |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2626 HRESULT hr; |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2627 |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2628 hr = build_video_chain(priv); |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2629 if(FAILED(hr)) |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2630 return 0; |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2631 |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2632 hr = build_audio_chain(priv); |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2633 if(FAILED(hr)) |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2634 return 0; |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2635 |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2636 hr = build_vbi_chain(priv); |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2637 if(FAILED(hr)) |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2638 return 0; |
7d74c1a2c840
Move chains building code into separate routines.
voroshil
parents:
25054
diff
changeset
|
2639 |
24744 | 2640 /* |
2641 Graph is ready to capture. Starting graph. | |
2642 */ | |
2643 if (mp_msg_test(MSGT_TV, MSGL_DBG2)) { | |
2644 mp_msg(MSGT_TV, MSGL_DBG2, "Debug pause 10sec\n"); | |
2645 usec_sleep(10000000); | |
2646 mp_msg(MSGT_TV, MSGL_DBG2, "Debug pause end\n"); | |
2647 } | |
2648 if (!priv->pMediaControl) { | |
2649 mp_msg(MSGT_TV,MSGL_ERR,MSGTR_TVI_DS_UnableGetMediaControlInterface,(unsigned int)E_POINTER); | |
2650 return 0; | |
2651 } | |
2652 hr = OLE_CALL(priv->pMediaControl, Run); | |
2653 if (FAILED(hr)) { | |
2654 mp_msg(MSGT_TV,MSGL_ERR,MSGTR_TVI_DS_UnableStartGraph, (unsigned int)hr); | |
2655 return 0; | |
2656 } | |
2657 mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Graph is started.\n"); | |
2658 priv->state = 1; | |
2659 | |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
2660 return 1; |
24744 | 2661 } |
2662 | |
2663 /** | |
2664 * \brief driver initialization | |
2665 * | |
2666 * \param priv driver's private data structure | |
2667 * | |
2668 * \return 1 if success, 0 - otherwise | |
2669 */ | |
2670 static int init(priv_t * priv) | |
2671 { | |
2672 HRESULT hr; | |
2673 int result = 0; | |
2674 long lInput, lTunerInput; | |
2675 IEnumFilters *pEnum; | |
2676 IBaseFilter *pFilter; | |
2677 IPin *pVPOutPin; | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2678 int i; |
24744 | 2679 |
2680 priv->state=0; | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2681 |
24744 | 2682 CoInitialize(NULL); |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2683 |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2684 for(i=0; i<3;i++) |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2685 priv->chains[i] = calloc(1, sizeof(chain_t)); |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2686 |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2687 priv->chains[0]->type=video; |
25080 | 2688 priv->chains[0]->majortype=&MEDIATYPE_Video; |
25094
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2689 priv->chains[0]->pin_category=&PIN_CATEGORY_CAPTURE; |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2690 priv->chains[1]->type=audio; |
25080 | 2691 priv->chains[1]->majortype=&MEDIATYPE_Audio; |
25094
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2692 priv->chains[1]->pin_category=&PIN_CATEGORY_CAPTURE; |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2693 priv->chains[2]->type=vbi; |
25080 | 2694 priv->chains[2]->majortype=&MEDIATYPE_VBI; |
25094
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2695 priv->chains[2]->pin_category=&PIN_CATEGORY_VBI; |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2696 |
24744 | 2697 do{ |
2698 hr = CoCreateInstance((GUID *) & CLSID_FilterGraph, NULL, | |
2699 CLSCTX_INPROC_SERVER, &IID_IGraphBuilder, | |
2700 (void **) &priv->pGraph); | |
2701 if(FAILED(hr)){ | |
2702 mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: CoCreateInstance(FilterGraph) call failed. Error:0x%x\n", (unsigned int)hr); | |
2703 break; | |
2704 } | |
2705 //Debug | |
2706 if (mp_msg_test(MSGT_TV, MSGL_DBG2)) { | |
2707 AddToRot((IUnknown *) priv->pGraph, &(priv->dwRegister)); | |
2708 } | |
2709 | |
2710 hr = CoCreateInstance((GUID *) & CLSID_CaptureGraphBuilder2, NULL, | |
2711 CLSCTX_INPROC_SERVER, &IID_ICaptureGraphBuilder2, | |
2712 (void **) &priv->pBuilder); | |
2713 if(FAILED(hr)){ | |
2714 mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: CoCreateInstance(CaptureGraphBuilder) call failed. Error:0x%x\n", (unsigned int)hr); | |
2715 break; | |
2716 } | |
2717 | |
2718 hr = OLE_CALL_ARGS(priv->pBuilder, SetFiltergraph, priv->pGraph); | |
2719 if(FAILED(hr)){ | |
2720 mp_msg(MSGT_TV,MSGL_ERR, "tvi_dshow: SetFiltergraph call failed. Error:0x%x\n",(unsigned int)hr); | |
2721 break; | |
2722 } | |
2723 | |
2724 mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Searching for available video capture devices\n"); | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2725 priv->chains[0]->pCaptureFilter = find_capture_device(priv->dev_index, &CLSID_VideoInputDeviceCategory); |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2726 if(!priv->chains[0]->pCaptureFilter){ |
24744 | 2727 mp_msg(MSGT_TV,MSGL_ERR, MSGTR_TVI_DS_NoVideoCaptureDevice); |
2728 break; | |
2729 } | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2730 hr = OLE_CALL_ARGS(priv->pGraph, AddFilter, priv->chains[0]->pCaptureFilter, NULL); |
24744 | 2731 if(FAILED(hr)){ |
2732 mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Unable to add video capture device to Directshow graph. Error:0x%x\n", (unsigned int)hr); | |
2733 break; | |
2734 } | |
2735 mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Searching for available audio capture devices\n"); | |
2736 if (priv->adev_index != -1) { | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2737 priv->chains[1]->pCaptureFilter = find_capture_device(priv->adev_index, &CLSID_AudioInputDeviceCategory); //output available audio edevices |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2738 if(!priv->chains[1]->pCaptureFilter){ |
24744 | 2739 mp_msg(MSGT_TV,MSGL_ERR, MSGTR_TVI_DS_NoAudioCaptureDevice); |
2740 break; | |
2741 } | |
2742 | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2743 hr = OLE_CALL_ARGS(priv->pGraph, AddFilter, priv->chains[1]->pCaptureFilter, NULL); |
24744 | 2744 if(FAILED(hr)){ |
2745 mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: Unable to add audio capture device to Directshow graph. Error:0x%x\n", (unsigned int)hr); | |
2746 break; | |
2747 } | |
2748 } else | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2749 hr = OLE_QUERYINTERFACE(priv->chains[0]->pCaptureFilter, IID_IBaseFilter, priv->chains[1]->pCaptureFilter); |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2750 |
25082
b63b4b599cbe
Add capture filter's pointer to vbi chain structure too.
voroshil
parents:
25081
diff
changeset
|
2751 /* increase refrence counter for capture filter ad store pointer into vbi chain structure too */ |
b63b4b599cbe
Add capture filter's pointer to vbi chain structure too.
voroshil
parents:
25081
diff
changeset
|
2752 hr = OLE_QUERYINTERFACE(priv->chains[0]->pCaptureFilter, IID_IBaseFilter, priv->chains[2]->pCaptureFilter); |
b63b4b599cbe
Add capture filter's pointer to vbi chain structure too.
voroshil
parents:
25081
diff
changeset
|
2753 |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2754 hr = OLE_QUERYINTERFACE(priv->chains[0]->pCaptureFilter, IID_IAMVideoProcAmp,priv->pVideoProcAmp); |
24744 | 2755 if (FAILED(hr) && hr != E_NOINTERFACE) |
2756 mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Get IID_IAMVideoProcAmp failed (0x%x).\n", (unsigned int)hr); | |
2757 | |
2758 if (hr != S_OK) { | |
2759 mp_msg(MSGT_TV, MSGL_INFO, MSGTR_TVI_DS_VideoAdjustigNotSupported); | |
2760 priv->pVideoProcAmp = NULL; | |
2761 } | |
2762 | |
2763 hr = OLE_CALL_ARGS(priv->pBuilder, FindInterface, | |
2764 &PIN_CATEGORY_CAPTURE, | |
25080 | 2765 priv->chains[0]->majortype, |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2766 priv->chains[0]->pCaptureFilter, |
24744 | 2767 &IID_IAMCrossbar, (void **) &(priv->pCrossbar)); |
2768 if (FAILED(hr)) { | |
2769 mp_msg(MSGT_TV, MSGL_INFO, MSGTR_TVI_DS_SelectingInputNotSupported); | |
2770 priv->pCrossbar = NULL; | |
2771 } | |
2772 | |
2773 if (priv->tv_param->amode >= 0) { | |
2774 IAMTVAudio *pTVAudio; | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2775 hr = OLE_CALL_ARGS(priv->pBuilder, FindInterface, NULL, NULL,priv->chains[0]->pCaptureFilter,&IID_IAMTVAudio, (void *) &pTVAudio); |
24744 | 2776 if (hr == S_OK) { |
2777 switch (priv->tv_param->amode) { | |
2778 case 0: | |
2779 hr = OLE_CALL_ARGS(pTVAudio, put_TVAudioMode, AMTVAUDIO_MODE_MONO); | |
2780 break; | |
2781 case 1: | |
2782 hr = OLE_CALL_ARGS(pTVAudio, put_TVAudioMode, AMTVAUDIO_MODE_STEREO); | |
2783 break; | |
2784 case 2: | |
2785 hr = OLE_CALL_ARGS(pTVAudio, put_TVAudioMode, | |
2786 AMTVAUDIO_MODE_LANG_A); | |
2787 break; | |
2788 case 3: | |
2789 hr = OLE_CALL_ARGS(pTVAudio, put_TVAudioMode, | |
2790 AMTVAUDIO_MODE_LANG_B); | |
2791 break; | |
2792 } | |
2793 OLE_RELEASE_SAFE(pTVAudio); | |
2794 if (FAILED(hr)) | |
2795 mp_msg(MSGT_TV, MSGL_WARN, MSGTR_TVI_DS_UnableSetAudioMode, priv->tv_param->amode,(unsigned int)hr); | |
2796 } | |
2797 } | |
25094
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2798 |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2799 // Video chain initialization |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2800 hr = init_chain_common(priv->pBuilder, priv->chains[0]); |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2801 if(FAILED(hr)) |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2802 break; |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2803 |
25125
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2804 /* |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2805 Audio chain initialization |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2806 Since absent audio stream is not fatal, |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2807 at least one NULL pointer should be kept in format arrays |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2808 (to avoid another additional check everywhere for array presence). |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2809 */ |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2810 hr = init_chain_common(priv->pBuilder, priv->chains[1]); |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2811 if(FAILED(hr)) |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2812 { |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2813 mp_msg(MSGT_TV, MSGL_V, "tvi_dshow: Unable to initialize audio chain (Error:0x%x). Audio disabled\n", (unsigned long)hr); |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2814 priv->chains[1]->arpmt=calloc(1, sizeof(AM_MEDIA_TYPE*)); |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2815 priv->chains[1]->arStreamCaps=calloc(1, sizeof(void*)); |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2816 } |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2817 |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2818 /* |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2819 VBI chain initialization |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2820 Since absent VBI stream is not fatal, |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2821 at least one NULL pointer should be kept in format arrays |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2822 (to avoid another additional check everywhere for array presence). |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2823 */ |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2824 hr = init_chain_common(priv->pBuilder, priv->chains[2]); |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2825 if(FAILED(hr)) |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2826 { |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2827 mp_msg(MSGT_TV, MSGL_V, "tvi_dshow: Unable to initialize VBI chain (Error:0x%x). Teletext disabled\n", (unsigned long)hr); |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2828 priv->chains[2]->arpmt=calloc(1, sizeof(AM_MEDIA_TYPE*)); |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2829 priv->chains[2]->arStreamCaps=calloc(1, sizeof(void*)); |
a1e6345207a1
§³reate empty format arrays in case of error in init_chain_common.
voroshil
parents:
25105
diff
changeset
|
2830 } |
25094
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2831 |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2832 if (!priv->chains[0]->pStreamConfig) |
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2833 mp_msg(MSGT_TV, MSGL_INFO, MSGTR_TVI_DS_ChangingWidthHeightNotSupported); |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2834 |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2835 if (!priv->chains[0]->arpmt[priv->chains[0]->nFormatUsed] |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2836 || !extract_video_format(priv->chains[0]->arpmt[priv->chains[0]->nFormatUsed], |
24744 | 2837 &(priv->fcc), &(priv->width), |
2838 &(priv->height))) { | |
2839 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TVI_DS_ErrorParsingVideoFormatStruct); | |
2840 break; | |
2841 } | |
25094
e27cb70d2302
Move code related to chain initialization and similar
voroshil
parents:
25093
diff
changeset
|
2842 |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2843 if (priv->chains[1]->arpmt[priv->chains[1]->nFormatUsed]) { |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2844 if (!extract_audio_format(priv->chains[1]->pmt, &(priv->samplerate), NULL, NULL)) { |
24744 | 2845 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TVI_DS_ErrorParsingAudioFormatStruct); |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2846 DisplayMediaType("audio format failed",priv->chains[1]->arpmt[priv->chains[1]->nFormatUsed]); |
24744 | 2847 break; |
2848 } | |
2849 } | |
2850 | |
2851 hr = OLE_QUERYINTERFACE(priv->pGraph, IID_IMediaControl,priv->pMediaControl); | |
2852 if(FAILED(hr)){ | |
2853 mp_msg(MSGT_TV,MSGL_ERR, MSGTR_TVI_DS_UnableGetMediaControlInterface,(unsigned int)hr); | |
2854 break; | |
2855 } | |
2856 hr = OLE_CALL_ARGS(priv->pBuilder, FindInterface, | |
2857 &PIN_CATEGORY_CAPTURE, NULL, | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2858 priv->chains[0]->pCaptureFilter, |
24744 | 2859 &IID_IAMTVTuner, (void **) &(priv->pTVTuner)); |
2860 | |
2861 if (!priv->pTVTuner) { | |
2862 mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Unable to access IAMTVTuner (0x%x)\n", (unsigned int)hr); | |
2863 } | |
2864 | |
2865 // shows Tuner capabilities | |
2866 get_capabilities(priv); | |
2867 | |
2868 if (priv->pTVTuner) { | |
2869 hr = OLE_CALL_ARGS(priv->pTVTuner, put_CountryCode, | |
2870 chanlist2country(priv->tv_param->chanlist)); | |
2871 if(FAILED(hr)){ | |
2872 mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: Call to put_CountryCode failed. Error:0x%x\n",(unsigned int)hr); | |
2873 } | |
2874 | |
2875 hr = OLE_CALL_ARGS(priv->pTVTuner, put_Mode, AMTUNER_MODE_TV); | |
2876 if(FAILED(hr)){ | |
2877 mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: Call to put_Mode failed. Error:0x%x\n",(unsigned int)hr); | |
2878 break; | |
2879 } | |
2880 | |
2881 hr = OLE_CALL_ARGS(priv->pTVTuner, get_ConnectInput, &lInput); | |
2882 if(FAILED(hr)){ | |
2883 mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: Call to get_ConnectInput failed. Error:0x%x\n",(unsigned int)hr); | |
2884 break; | |
2885 } | |
2886 | |
2887 /* small hack */ | |
2888 lTunerInput = strstr(priv->tv_param->chanlist, "cable") ? TunerInputCable : TunerInputAntenna; | |
2889 | |
2890 hr = OLE_CALL_ARGS(priv->pTVTuner, put_InputType, lInput, lTunerInput); | |
2891 if(FAILED(hr)){ | |
2892 mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: Call to put_InputType failed. Error:0x%x\n",(unsigned int)hr); | |
2893 break; | |
2894 } | |
2895 | |
2896 } | |
2897 | |
2898 /** | |
2899 for VIVO cards we should check if preview pin is available on video capture device. | |
2900 If it is not, we have to connect Video Port Manager filter to VP pin of capture device filter. | |
2901 Otherwise we will get 0x8007001f (Device is not functioning properly) when attempting to start graph | |
2902 */ | |
2903 hr = OLE_CALL_ARGS(priv->pBuilder, FindPin, | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
2904 (IUnknown *) priv->chains[0]->pCaptureFilter, |
24744 | 2905 PINDIR_OUTPUT, |
2906 &PIN_CATEGORY_VIDEOPORT, NULL, FALSE, | |
2907 0, (IPin **) & pVPOutPin); | |
2908 if (SUCCEEDED(hr)) { | |
2909 hr = OLE_CALL_ARGS(priv->pGraph, Render, pVPOutPin); | |
2910 OLE_RELEASE_SAFE(pVPOutPin); | |
2911 | |
2912 if (FAILED(hr)) { | |
2913 mp_msg(MSGT_TV,MSGL_ERR, MSGTR_TVI_DS_UnableTerminateVPPin, (unsigned int)hr); | |
2914 break; | |
2915 } | |
2916 } | |
2917 | |
2918 OLE_CALL_ARGS(priv->pGraph, EnumFilters, &pEnum); | |
2919 while (OLE_CALL_ARGS(pEnum, Next, 1, &pFilter, NULL) == S_OK) { | |
2920 LPVIDEOWINDOW pVideoWindow; | |
2921 hr = OLE_QUERYINTERFACE(pFilter, IID_IVideoWindow, pVideoWindow); | |
2922 if (SUCCEEDED(hr)) | |
2923 { | |
2924 if(priv->tv_param->hidden_vp_renderer){ | |
2925 OLE_CALL_ARGS(pVideoWindow,put_Visible,/* OAFALSE*/ 0); | |
2926 OLE_CALL_ARGS(pVideoWindow,put_AutoShow,/* OAFALSE*/ 0); | |
2927 }else | |
2928 { | |
2929 OLE_CALL_ARGS(priv->pGraph, RemoveFilter, pFilter); | |
2930 } | |
2931 OLE_RELEASE_SAFE(pVideoWindow); | |
2932 } | |
2933 OLE_RELEASE_SAFE(pFilter); | |
2934 } | |
2935 OLE_RELEASE_SAFE(pEnum); | |
2936 if(priv->tv_param->system_clock) | |
2937 { | |
2938 LPREFERENCECLOCK rc; | |
2939 IBaseFilter* pBF; | |
2940 hr = CoCreateInstance((GUID *) & CLSID_SystemClock, NULL, | |
2941 CLSCTX_INPROC_SERVER, &IID_IReferenceClock, | |
2942 (void *) &rc); | |
2943 | |
2944 OLE_QUERYINTERFACE(priv->pBuilder,IID_IBaseFilter,pBF); | |
2945 OLE_CALL_ARGS(pBF,SetSyncSource,rc); | |
2946 } | |
27370
14c5017f40d2
Change a bunch of video/audio-output-specific preprocessor directives from
diego
parents:
26756
diff
changeset
|
2947 #ifdef CONFIG_TV_TELETEXT |
24744 | 2948 if(vbi_get_props(priv,&(priv->tsp))!=TVI_CONTROL_TRUE) |
2949 break; | |
2950 #endif | |
2951 result = 1; | |
2952 } while(0); | |
2953 | |
2954 if (!result){ | |
2955 mp_msg(MSGT_TV,MSGL_ERR, MSGTR_TVI_DS_GraphInitFailure); | |
2956 uninit(priv); | |
2957 } | |
2958 return result; | |
2959 } | |
2960 | |
2961 /** | |
25085
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2962 * \brief chain uninitialization |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2963 * \param chain chain data structure |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2964 */ |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2965 static void destroy_chain(chain_t *chain) |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2966 { |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2967 int i; |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2968 |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2969 if(!chain) |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2970 return; |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2971 |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2972 OLE_RELEASE_SAFE(chain->pStreamConfig); |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2973 OLE_RELEASE_SAFE(chain->pCaptureFilter); |
25086
e91503fbf524
Move pointer to SampleGrabber filter into chain structure.
voroshil
parents:
25085
diff
changeset
|
2974 OLE_RELEASE_SAFE(chain->pCSGCB); |
25087
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
2975 OLE_RELEASE_SAFE(chain->pCapturePin); |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
2976 OLE_RELEASE_SAFE(chain->pSGIn); |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
2977 OLE_RELEASE_SAFE(chain->pSG); |
edc7391db7f5
New routine for reconnecting two pins with new media type
voroshil
parents:
25086
diff
changeset
|
2978 OLE_RELEASE_SAFE(chain->pSGF); |
25086
e91503fbf524
Move pointer to SampleGrabber filter into chain structure.
voroshil
parents:
25085
diff
changeset
|
2979 |
25085
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2980 if (chain->pmt) |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2981 DeleteMediaType(chain->pmt); |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2982 |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2983 if (chain->arpmt) { |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2984 for (i = 0; chain->arpmt[i]; i++) { |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2985 DeleteMediaType(chain->arpmt[i]); |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2986 } |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2987 free(chain->arpmt); |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2988 } |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2989 |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2990 if (chain->arStreamCaps) { |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2991 for (i = 0; chain->arStreamCaps[i]; i++) { |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2992 free(chain->arStreamCaps[i]); |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2993 } |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2994 free(chain->arStreamCaps); |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2995 } |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2996 |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2997 if (chain->rbuf) { |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2998 destroy_ringbuffer(chain->rbuf); |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
2999 free(chain->rbuf); |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
3000 chain->rbuf = NULL; |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
3001 } |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
3002 free(chain); |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
3003 } |
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
3004 /** |
24744 | 3005 * \brief driver uninitialization |
3006 * | |
3007 * \param priv driver's private data structure | |
3008 * | |
3009 * \return always 1 | |
3010 */ | |
3011 static int uninit(priv_t * priv) | |
3012 { | |
3013 int i; | |
3014 if (!priv) | |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
3015 return 1; |
24744 | 3016 //Debug |
3017 if (priv->dwRegister) { | |
3018 RemoveFromRot(priv->dwRegister); | |
3019 } | |
27370
14c5017f40d2
Change a bunch of video/audio-output-specific preprocessor directives from
diego
parents:
26756
diff
changeset
|
3020 #ifdef CONFIG_TV_TELETEXT |
24744 | 3021 teletext_control(priv->priv_vbi,TV_VBI_CONTROL_STOP,(void*)1); |
3022 #endif | |
3023 //stop audio grabber thread | |
3024 | |
3025 if (priv->state && priv->pMediaControl) { | |
3026 OLE_CALL(priv->pMediaControl, Stop); | |
3027 } | |
3028 OLE_RELEASE_SAFE(priv->pMediaControl); | |
3029 priv->state = 0; | |
3030 | |
3031 if (priv->pGraph) { | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3032 if (priv->chains[0]->pCaptureFilter) |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3033 OLE_CALL_ARGS(priv->pGraph, RemoveFilter, priv->chains[0]->pCaptureFilter); |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3034 if (priv->chains[1]->pCaptureFilter) |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3035 OLE_CALL_ARGS(priv->pGraph, RemoveFilter, priv->chains[1]->pCaptureFilter); |
24744 | 3036 } |
3037 OLE_RELEASE_SAFE(priv->pCrossbar); | |
3038 OLE_RELEASE_SAFE(priv->pVideoProcAmp); | |
3039 OLE_RELEASE_SAFE(priv->pGraph); | |
3040 OLE_RELEASE_SAFE(priv->pBuilder); | |
3041 if(priv->freq_table){ | |
3042 priv->freq_table_len=-1; | |
3043 free(priv->freq_table); | |
3044 priv->freq_table=NULL; | |
3045 } | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3046 |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3047 for(i=0; i<3;i++) |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3048 { |
25085
da7c8d1b7a36
Move common chain uninit code into separate routine.
voroshil
parents:
25084
diff
changeset
|
3049 destroy_chain(priv->chains[i]); |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3050 priv->chains[i] = NULL; |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3051 } |
24744 | 3052 CoUninitialize(); |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
3053 return 1; |
24744 | 3054 } |
3055 | |
3056 /** | |
3057 * \brief driver pre-initialization | |
3058 * | |
3059 * \param device string, containing device name in form "x[.y]", where x is video capture device | |
3060 * (default: 0, first available); y (if given) sets audio capture device | |
3061 * | |
3062 * \return 1 if success,0 - otherwise | |
3063 */ | |
3064 static tvi_handle_t *tvi_init_dshow(tv_param_t* tv_param) | |
3065 { | |
3066 tvi_handle_t *h; | |
3067 priv_t *priv; | |
3068 int a; | |
3069 | |
3070 h = new_handle(); | |
3071 if (!h) | |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
3072 return NULL; |
24744 | 3073 |
3074 priv = h->priv; | |
3075 | |
3076 memset(priv, 0, sizeof(priv_t)); | |
3077 priv->direct_setfreq_call = 1; //first using direct call. if it fails, workaround will be enabled | |
3078 priv->direct_getfreq_call = 1; //first using direct call. if it fails, workaround will be enabled | |
3079 priv->adev_index = -1; | |
3080 priv->freq_table_len=-1; | |
3081 priv->tv_param=tv_param; | |
3082 | |
3083 if (tv_param->device) { | |
3084 if (sscanf(tv_param->device, "%d", &a) == 1) { | |
3085 priv->dev_index = a; | |
3086 } else { | |
3087 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TVI_DS_WrongDeviceParam, tv_param->device); | |
3088 free_handle(h); | |
3089 return NULL; | |
3090 } | |
3091 if (priv->dev_index < 0) { | |
3092 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TVI_DS_WrongDeviceIndex, a); | |
3093 free_handle(h); | |
3094 return NULL; | |
3095 } | |
3096 } | |
3097 if (tv_param->adevice) { | |
3098 if (sscanf(tv_param->adevice, "%d", &a) == 1) { | |
3099 priv->adev_index = a; | |
3100 } else { | |
3101 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TVI_DS_WrongADeviceParam, tv_param->adevice); | |
3102 free_handle(h); | |
3103 return NULL; | |
3104 } | |
3105 if (priv->dev_index < 0) { | |
3106 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TVI_DS_WrongADeviceIndex, a); | |
3107 free_handle(h); | |
3108 return NULL; | |
3109 } | |
3110 } | |
3111 return h; | |
3112 } | |
3113 | |
3114 /** | |
3115 * \brief driver's ioctl handler | |
3116 * | |
3117 * \param priv driver's private data structure | |
3118 * \param cmd ioctl command | |
3119 * \param arg ioct command's parameter | |
3120 * | |
3121 * \return TVI_CONTROL_TRUE if success | |
3122 * \return TVI_CONTROL_FALSE if failure | |
3123 * \return TVI_CONTROL_UNKNOWN if unknowm cmd called | |
3124 */ | |
3125 static int control(priv_t * priv, int cmd, void *arg) | |
3126 { | |
3127 switch (cmd) { | |
3128 /* need rewrite */ | |
3129 case TVI_CONTROL_VID_SET_FORMAT: | |
3130 { | |
25126
8152446e42b1
Move requested format at top and shift all oters down
voroshil
parents:
25125
diff
changeset
|
3131 int fcc, i,j; |
8152446e42b1
Move requested format at top and shift all oters down
voroshil
parents:
25125
diff
changeset
|
3132 void* tmp,*tmp2; |
25068
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3133 int result = TVI_CONTROL_TRUE; |
25063
29260745e4fa
Pass all available formats to chain building routine and
voroshil
parents:
25061
diff
changeset
|
3134 |
24744 | 3135 if (priv->state) |
3136 return TVI_CONTROL_FALSE; | |
3137 fcc = *(int *) arg; | |
3138 | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3139 if(!priv->chains[0]->arpmt) |
24744 | 3140 return TVI_CONTROL_FALSE; |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3141 for (i = 0; priv->chains[0]->arpmt[i]; i++) |
24744 | 3142 if (check_video_format |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3143 (priv->chains[0]->arpmt[i], fcc, priv->width, priv->height)) |
24744 | 3144 break; |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3145 if (!priv->chains[0]->arpmt[i]) |
25068
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3146 { |
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3147 int fps = 0; |
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3148 VIDEOINFOHEADER* Vhdr = NULL; |
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3149 AM_MEDIA_TYPE *pmt; |
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3150 |
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3151 mp_msg(MSGT_TV, MSGL_V, "tvi_dshow: will try also use undeclared video format: %dx%d, %s\n",priv->width, priv->height, vo_format_name(fcc)); |
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3152 |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3153 if (priv->chains[0]->arpmt[0]) |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3154 Vhdr = (VIDEOINFOHEADER *) priv->chains[0]->arpmt[0]->pbFormat; |
25068
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3155 |
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3156 if(Vhdr && Vhdr->bmiHeader.biSizeImage) |
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3157 fps = Vhdr->dwBitRate / (8 * Vhdr->bmiHeader.biSizeImage); |
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3158 |
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3159 pmt=create_video_format(fcc, priv->width, priv->height, fps); |
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3160 if(!pmt) |
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3161 { |
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3162 mp_msg(MSGT_TV, MSGL_V, "tvi_dshow: Unable to create AM_MEDIA_TYPE structure for given format\n"); |
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3163 return TVI_CONTROL_FALSE; |
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3164 } |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3165 priv->chains[0]->arpmt=realloc(priv->chains[0]->arpmt, (i+2)*sizeof(AM_MEDIA_TYPE*)); |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3166 priv->chains[0]->arpmt[i+1] = NULL; |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3167 priv->chains[0]->arpmt[i] = pmt; |
25068
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3168 |
25105 | 3169 priv->chains[0]->arStreamCaps=realloc(priv->chains[0]->arStreamCaps, (i+2)*sizeof(void*)); |
25096 | 3170 priv->chains[0]->arpmt[i+1] = NULL; |
3171 | |
25068
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3172 result = TVI_CONTROL_FALSE; |
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3173 } |
24744 | 3174 |
25126
8152446e42b1
Move requested format at top and shift all oters down
voroshil
parents:
25125
diff
changeset
|
3175 |
8152446e42b1
Move requested format at top and shift all oters down
voroshil
parents:
25125
diff
changeset
|
3176 tmp=priv->chains[0]->arpmt[i]; |
8152446e42b1
Move requested format at top and shift all oters down
voroshil
parents:
25125
diff
changeset
|
3177 tmp2=priv->chains[0]->arStreamCaps[i]; |
8152446e42b1
Move requested format at top and shift all oters down
voroshil
parents:
25125
diff
changeset
|
3178 for(j=i; j>0; j--) |
8152446e42b1
Move requested format at top and shift all oters down
voroshil
parents:
25125
diff
changeset
|
3179 { |
8152446e42b1
Move requested format at top and shift all oters down
voroshil
parents:
25125
diff
changeset
|
3180 priv->chains[0]->arpmt[j] = priv->chains[0]->arpmt[j-1]; |
8152446e42b1
Move requested format at top and shift all oters down
voroshil
parents:
25125
diff
changeset
|
3181 priv->chains[0]->arStreamCaps[j] = priv->chains[0]->arStreamCaps[j-1]; |
8152446e42b1
Move requested format at top and shift all oters down
voroshil
parents:
25125
diff
changeset
|
3182 } |
8152446e42b1
Move requested format at top and shift all oters down
voroshil
parents:
25125
diff
changeset
|
3183 priv->chains[0]->arpmt[0] = tmp; |
8152446e42b1
Move requested format at top and shift all oters down
voroshil
parents:
25125
diff
changeset
|
3184 priv->chains[0]->arStreamCaps[0] = tmp2; |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3185 |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3186 priv->chains[0]->nFormatUsed = 0; |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3187 |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3188 if (priv->chains[0]->pmt) |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3189 DeleteMediaType(priv->chains[0]->pmt); |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3190 priv->chains[0]->pmt = |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3191 CreateMediaType(priv->chains[0]->arpmt[priv->chains[0]->nFormatUsed]); |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3192 DisplayMediaType("VID_SET_FORMAT", priv->chains[0]->pmt); |
24744 | 3193 /* |
3194 Setting width & height to preferred by driver values | |
3195 */ | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3196 extract_video_format(priv->chains[0]->arpmt[priv->chains[0]->nFormatUsed], |
24744 | 3197 &(priv->fcc), &(priv->width), |
3198 &(priv->height)); | |
25068
4b14d188ed34
Add all passed to VID_SET_FORMAT formats to the end of
voroshil
parents:
25067
diff
changeset
|
3199 return result; |
24744 | 3200 } |
3201 case TVI_CONTROL_VID_GET_FORMAT: | |
3202 { | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3203 if(!priv->chains[0]->pmt) |
24744 | 3204 return TVI_CONTROL_FALSE; |
25067
5abe2c29b7d8
Ensure that when VID_GET_FORMAT ioctl is called,
voroshil
parents:
25066
diff
changeset
|
3205 /* |
5abe2c29b7d8
Ensure that when VID_GET_FORMAT ioctl is called,
voroshil
parents:
25066
diff
changeset
|
3206 Build video chain (for video format negotiation). |
5abe2c29b7d8
Ensure that when VID_GET_FORMAT ioctl is called,
voroshil
parents:
25066
diff
changeset
|
3207 If this was done before, routine will do nothing. |
5abe2c29b7d8
Ensure that when VID_GET_FORMAT ioctl is called,
voroshil
parents:
25066
diff
changeset
|
3208 */ |
5abe2c29b7d8
Ensure that when VID_GET_FORMAT ioctl is called,
voroshil
parents:
25066
diff
changeset
|
3209 build_video_chain(priv); |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3210 DisplayMediaType("VID_GET_FORMAT", priv->chains[0]->pmt); |
24744 | 3211 if (priv->fcc) { |
3212 *(int *) arg = priv->fcc; | |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
3213 return TVI_CONTROL_TRUE; |
24744 | 3214 } else |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
3215 return TVI_CONTROL_FALSE; |
24744 | 3216 } |
3217 case TVI_CONTROL_VID_SET_WIDTH: | |
3218 { | |
3219 VIDEO_STREAM_CONFIG_CAPS *pCaps; | |
3220 VIDEOINFOHEADER *Vhdr; | |
3221 int width = *(int *) arg; | |
3222 if (priv->state) | |
3223 return TVI_CONTROL_FALSE; | |
3224 | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3225 pCaps = priv->chains[0]->arStreamCaps[priv->chains[0]->nFormatUsed]; |
24744 | 3226 if (!pCaps) |
3227 return TVI_CONTROL_FALSE; | |
3228 if (width < pCaps->MinOutputSize.cx | |
3229 || width > pCaps->MaxOutputSize.cx) | |
3230 return TVI_CONTROL_FALSE; | |
3231 | |
3232 if (width % pCaps->OutputGranularityX) | |
3233 return TVI_CONTROL_FALSE; | |
3234 | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3235 if (!priv->chains[0]->pmt || !priv->chains[0]->pmt->pbFormat) |
24744 | 3236 return TVI_CONTROL_FALSE; |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3237 Vhdr = (VIDEOINFOHEADER *) priv->chains[0]->pmt->pbFormat; |
24744 | 3238 Vhdr->bmiHeader.biWidth = width; |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3239 priv->chains[0]->pmt->lSampleSize = Vhdr->bmiHeader.biSizeImage = |
24744 | 3240 labs(Vhdr->bmiHeader.biBitCount * Vhdr->bmiHeader.biWidth * |
3241 Vhdr->bmiHeader.biHeight) >> 3; | |
3242 | |
3243 priv->width = width; | |
3244 | |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
3245 return TVI_CONTROL_TRUE; |
24744 | 3246 } |
3247 case TVI_CONTROL_VID_GET_WIDTH: | |
3248 { | |
3249 if (priv->width) { | |
3250 *(int *) arg = priv->width; | |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
3251 return TVI_CONTROL_TRUE; |
24744 | 3252 } else |
3253 return TVI_CONTROL_FALSE; | |
3254 } | |
3255 case TVI_CONTROL_VID_CHK_WIDTH: | |
3256 { | |
3257 VIDEO_STREAM_CONFIG_CAPS *pCaps; | |
3258 int width = *(int *) arg; | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3259 pCaps = priv->chains[0]->arStreamCaps[priv->chains[0]->nFormatUsed]; |
24744 | 3260 if (!pCaps) |
3261 return TVI_CONTROL_FALSE; | |
3262 if (width < pCaps->MinOutputSize.cx | |
3263 || width > pCaps->MaxOutputSize.cx) | |
3264 return TVI_CONTROL_FALSE; | |
3265 | |
3266 if (width % pCaps->OutputGranularityX) | |
3267 return TVI_CONTROL_FALSE; | |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
3268 return TVI_CONTROL_TRUE; |
24744 | 3269 } |
3270 case TVI_CONTROL_VID_SET_HEIGHT: | |
3271 { | |
3272 VIDEO_STREAM_CONFIG_CAPS *pCaps; | |
3273 VIDEOINFOHEADER *Vhdr; | |
3274 int height = *(int *) arg; | |
3275 if (priv->state) | |
3276 return TVI_CONTROL_FALSE; | |
3277 | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3278 pCaps = priv->chains[0]->arStreamCaps[priv->chains[0]->nFormatUsed]; |
24744 | 3279 if (!pCaps) |
3280 return TVI_CONTROL_FALSE; | |
3281 if (height < pCaps->MinOutputSize.cy | |
3282 || height > pCaps->MaxOutputSize.cy) | |
3283 return TVI_CONTROL_FALSE; | |
3284 | |
3285 if (height % pCaps->OutputGranularityY) | |
3286 return TVI_CONTROL_FALSE; | |
3287 | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3288 if (!priv->chains[0]->pmt || !priv->chains[0]->pmt->pbFormat) |
24744 | 3289 return TVI_CONTROL_FALSE; |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3290 Vhdr = (VIDEOINFOHEADER *) priv->chains[0]->pmt->pbFormat; |
24744 | 3291 |
3292 if (Vhdr->bmiHeader.biHeight < 0) | |
3293 Vhdr->bmiHeader.biHeight = -height; | |
3294 else | |
3295 Vhdr->bmiHeader.biHeight = height; | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3296 priv->chains[0]->pmt->lSampleSize = Vhdr->bmiHeader.biSizeImage = |
24744 | 3297 labs(Vhdr->bmiHeader.biBitCount * Vhdr->bmiHeader.biWidth * |
3298 Vhdr->bmiHeader.biHeight) >> 3; | |
3299 | |
3300 priv->height = height; | |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
3301 return TVI_CONTROL_TRUE; |
24744 | 3302 } |
3303 case TVI_CONTROL_VID_GET_HEIGHT: | |
3304 { | |
3305 if (priv->height) { | |
3306 *(int *) arg = priv->height; | |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
3307 return TVI_CONTROL_TRUE; |
24744 | 3308 } else |
3309 return TVI_CONTROL_FALSE; | |
3310 } | |
3311 case TVI_CONTROL_VID_CHK_HEIGHT: | |
3312 { | |
3313 VIDEO_STREAM_CONFIG_CAPS *pCaps; | |
3314 int height = *(int *) arg; | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3315 pCaps = priv->chains[0]->arStreamCaps[priv->chains[0]->nFormatUsed]; |
24744 | 3316 if (!pCaps) |
3317 return TVI_CONTROL_FALSE; | |
3318 if (height < pCaps->MinOutputSize.cy | |
3319 || height > pCaps->MaxOutputSize.cy) | |
3320 return TVI_CONTROL_FALSE; | |
3321 | |
3322 if (height % pCaps->OutputGranularityY) | |
3323 return TVI_CONTROL_FALSE; | |
3324 | |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
3325 return TVI_CONTROL_TRUE; |
24744 | 3326 } |
3327 case TVI_CONTROL_IS_AUDIO: | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3328 if (!priv->chains[1]->pmt) |
24744 | 3329 return TVI_CONTROL_FALSE; |
3330 else | |
3331 return TVI_CONTROL_TRUE; | |
3332 case TVI_CONTROL_IS_VIDEO: | |
3333 return TVI_CONTROL_TRUE; | |
3334 case TVI_CONTROL_AUD_GET_FORMAT: | |
3335 { | |
3336 *(int *) arg = AF_FORMAT_S16_LE; | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3337 if (!priv->chains[1]->pmt) |
24744 | 3338 return TVI_CONTROL_FALSE; |
3339 else | |
3340 return TVI_CONTROL_TRUE; | |
3341 } | |
3342 case TVI_CONTROL_AUD_GET_CHANNELS: | |
3343 { | |
3344 *(int *) arg = priv->channels; | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3345 if (!priv->chains[1]->pmt) |
24744 | 3346 return TVI_CONTROL_FALSE; |
3347 else | |
3348 return TVI_CONTROL_TRUE; | |
3349 } | |
3350 case TVI_CONTROL_AUD_SET_SAMPLERATE: | |
3351 { | |
3352 int i, samplerate; | |
3353 if (priv->state) | |
3354 return TVI_CONTROL_FALSE; | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3355 if (!priv->chains[1]->arpmt[0]) |
24744 | 3356 return TVI_CONTROL_FALSE; |
3357 | |
3358 samplerate = *(int *) arg;; | |
3359 | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3360 for (i = 0; priv->chains[1]->arpmt[i]; i++) |
24744 | 3361 if (check_audio_format |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3362 (priv->chains[1]->arpmt[i], samplerate, 16, priv->channels)) |
24744 | 3363 break; |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3364 if (!priv->chains[1]->arpmt[i]) { |
24744 | 3365 //request not found. failing back to first available |
3366 mp_msg(MSGT_TV, MSGL_WARN, MSGTR_TVI_DS_SamplerateNotsupported, samplerate); | |
3367 i = 0; | |
3368 } | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3369 if (priv->chains[1]->pmt) |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3370 DeleteMediaType(priv->chains[1]->pmt); |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3371 priv->chains[1]->pmt = CreateMediaType(priv->chains[1]->arpmt[i]); |
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3372 extract_audio_format(priv->chains[1]->arpmt[i], &(priv->samplerate), |
24744 | 3373 NULL, &(priv->channels)); |
3374 return TVI_CONTROL_TRUE; | |
3375 } | |
3376 case TVI_CONTROL_AUD_GET_SAMPLERATE: | |
3377 { | |
3378 *(int *) arg = priv->samplerate; | |
3379 if (!priv->samplerate) | |
3380 return TVI_CONTROL_FALSE; | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3381 if (!priv->chains[1]->pmt) |
24744 | 3382 return TVI_CONTROL_FALSE; |
3383 else | |
3384 return TVI_CONTROL_TRUE; | |
3385 } | |
3386 case TVI_CONTROL_AUD_GET_SAMPLESIZE: | |
3387 { | |
3388 WAVEFORMATEX *pWF; | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3389 if (!priv->chains[1]->pmt) |
24744 | 3390 return TVI_CONTROL_FALSE; |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3391 if (!priv->chains[1]->pmt->pbFormat) |
24744 | 3392 return TVI_CONTROL_FALSE; |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3393 pWF = (WAVEFORMATEX *) priv->chains[1]->pmt->pbFormat; |
24744 | 3394 *(int *) arg = pWF->wBitsPerSample / 8; |
3395 return TVI_CONTROL_TRUE; | |
3396 } | |
3397 case TVI_CONTROL_IS_TUNER: | |
3398 { | |
3399 if (!priv->pTVTuner) | |
3400 return TVI_CONTROL_FALSE; | |
3401 | |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
3402 return TVI_CONTROL_TRUE; |
24744 | 3403 } |
3404 case TVI_CONTROL_TUN_SET_NORM: | |
3405 { | |
3406 IAMAnalogVideoDecoder *pVD; | |
3407 long lAnalogFormat; | |
3408 int i; | |
3409 HRESULT hr; | |
3410 | |
3411 i = *(int *) arg; | |
3412 i--; | |
3413 if (i < 0 || i >= tv_available_norms_count) | |
3414 return TVI_CONTROL_FALSE; | |
3415 lAnalogFormat = tv_norms[tv_available_norms[i]].index; | |
3416 | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3417 hr = OLE_QUERYINTERFACE(priv->chains[0]->pCaptureFilter,IID_IAMAnalogVideoDecoder, pVD); |
24744 | 3418 if (hr != S_OK) |
3419 return TVI_CONTROL_FALSE; | |
25077 | 3420 hr = OLE_CALL_ARGS(pVD, put_TVFormat, lAnalogFormat); |
24744 | 3421 OLE_RELEASE_SAFE(pVD); |
3422 if (FAILED(hr)) | |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
3423 return TVI_CONTROL_FALSE; |
24744 | 3424 else |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
3425 return TVI_CONTROL_TRUE; |
24744 | 3426 } |
3427 case TVI_CONTROL_TUN_GET_NORM: | |
3428 { | |
3429 long lAnalogFormat; | |
3430 int i; | |
3431 HRESULT hr; | |
3432 IAMAnalogVideoDecoder *pVD; | |
3433 | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3434 hr = OLE_QUERYINTERFACE(priv->chains[0]->pCaptureFilter,IID_IAMAnalogVideoDecoder, pVD); |
24744 | 3435 if (hr == S_OK) { |
3436 hr = OLE_CALL_ARGS(pVD, get_TVFormat, &lAnalogFormat); | |
3437 OLE_RELEASE_SAFE(pVD); | |
3438 } | |
3439 | |
3440 if (FAILED(hr)) { //trying another method | |
3441 if (!priv->pTVTuner) | |
3442 return TVI_CONTROL_FALSE; | |
3443 hr=OLE_CALL_ARGS(priv->pTVTuner, get_TVFormat, &lAnalogFormat); | |
3444 if (FAILED(hr)) | |
3445 return TVI_CONTROL_FALSE; | |
3446 } | |
3447 for (i = 0; i < tv_available_norms_count; i++) { | |
3448 if (tv_norms[tv_available_norms[i]].index == lAnalogFormat) { | |
3449 *(int *) arg = i + 1; | |
3450 return TVI_CONTROL_TRUE; | |
3451 } | |
3452 } | |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
3453 return TVI_CONTROL_FALSE; |
24744 | 3454 } |
3455 case TVI_CONTROL_SPC_GET_NORMID: | |
3456 { | |
3457 int i; | |
3458 if (!priv->pTVTuner) | |
3459 return TVI_CONTROL_FALSE; | |
3460 for (i = 0; i < tv_available_norms_count; i++) { | |
3461 if (!strcasecmp | |
3462 (tv_norms[tv_available_norms[i]].name, (char *) arg)) { | |
3463 *(int *) arg = i + 1; | |
3464 return TVI_CONTROL_TRUE; | |
3465 } | |
3466 } | |
3467 return TVI_CONTROL_FALSE; | |
3468 } | |
3469 case TVI_CONTROL_SPC_SET_INPUT: | |
3470 { | |
3471 return set_crossbar_input(priv, *(int *) arg); | |
3472 } | |
3473 case TVI_CONTROL_TUN_GET_FREQ: | |
3474 { | |
3475 unsigned long lFreq; | |
3476 int ret; | |
3477 if (!priv->pTVTuner) | |
3478 return TVI_CONTROL_FALSE; | |
3479 | |
3480 ret = get_frequency(priv, &lFreq); | |
3481 lFreq = lFreq * 16 / 1000000; //convert from Hz to 1/16 MHz units | |
3482 | |
3483 *(unsigned long *) arg = lFreq; | |
3484 return ret; | |
3485 } | |
3486 case TVI_CONTROL_TUN_SET_FREQ: | |
3487 { | |
3488 unsigned long nFreq = *(unsigned long *) arg; | |
3489 if (!priv->pTVTuner) | |
3490 return TVI_CONTROL_FALSE; | |
3491 //convert to Hz | |
3492 nFreq = 1000000 * nFreq / 16; //convert from 1/16 MHz units to Hz | |
3493 return set_frequency(priv, nFreq); | |
3494 } | |
3495 case TVI_CONTROL_VID_SET_HUE: | |
3496 return set_control(priv, VideoProcAmp_Hue, *(int *) arg); | |
3497 case TVI_CONTROL_VID_GET_HUE: | |
3498 return get_control(priv, VideoProcAmp_Hue, (int *) arg); | |
3499 case TVI_CONTROL_VID_SET_CONTRAST: | |
3500 return set_control(priv, VideoProcAmp_Contrast, *(int *) arg); | |
3501 case TVI_CONTROL_VID_GET_CONTRAST: | |
3502 return get_control(priv, VideoProcAmp_Contrast, (int *) arg); | |
3503 case TVI_CONTROL_VID_SET_SATURATION: | |
3504 return set_control(priv, VideoProcAmp_Saturation, *(int *) arg); | |
3505 case TVI_CONTROL_VID_GET_SATURATION: | |
3506 return get_control(priv, VideoProcAmp_Saturation, (int *) arg); | |
3507 case TVI_CONTROL_VID_SET_BRIGHTNESS: | |
3508 return set_control(priv, VideoProcAmp_Brightness, *(int *) arg); | |
3509 case TVI_CONTROL_VID_GET_BRIGHTNESS: | |
3510 return get_control(priv, VideoProcAmp_Brightness, (int *) arg); | |
3511 | |
3512 case TVI_CONTROL_VID_GET_FPS: | |
3513 { | |
3514 VIDEOINFOHEADER *Vhdr; | |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3515 if (!priv->chains[0]->pmt) |
24744 | 3516 return TVI_CONTROL_FALSE; |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3517 if (!priv->chains[0]->pmt->pbFormat) |
24744 | 3518 return TVI_CONTROL_FALSE; |
25079
3dcf8e3e65d9
One step of code cleanup: move all variables, related
voroshil
parents:
25077
diff
changeset
|
3519 Vhdr = (VIDEOINFOHEADER *) priv->chains[0]->pmt->pbFormat; |
24744 | 3520 *(float *) arg = |
25028
2cae9470f53b
Fix FPS from bitrate calculation (was 8 times larger than real value).
voroshil
parents:
25019
diff
changeset
|
3521 (1.0 * Vhdr->dwBitRate) / (Vhdr->bmiHeader.biSizeImage * 8); |
24744 | 3522 return TVI_CONTROL_TRUE; |
3523 } | |
3524 case TVI_CONTROL_IMMEDIATE: | |
3525 priv->immediate_mode = 1; | |
3526 return TVI_CONTROL_TRUE; | |
27370
14c5017f40d2
Change a bunch of video/audio-output-specific preprocessor directives from
diego
parents:
26756
diff
changeset
|
3527 #ifdef CONFIG_TV_TELETEXT |
24744 | 3528 case TVI_CONTROL_VBI_INIT: |
3529 { | |
3530 void* ptr; | |
3531 ptr=&(priv->tsp); | |
3532 if(teletext_control(NULL,TV_VBI_CONTROL_START,&ptr)==TVI_CONTROL_TRUE) | |
3533 priv->priv_vbi=ptr; | |
3534 else | |
3535 priv->priv_vbi=NULL; | |
3536 return TVI_CONTROL_TRUE; | |
3537 } | |
3538 default: | |
3539 return teletext_control(priv->priv_vbi,cmd,arg); | |
3540 #endif | |
3541 } | |
26756
c43ce7268677
cosmetics: Remove useless parentheses from return statements.
diego
parents:
26737
diff
changeset
|
3542 return TVI_CONTROL_UNKNOWN; |
24744 | 3543 } |