2012-02-03 42 views
1

我想提供一個選項,用於在使用CaptureElement/MediaCapture顯示預覽的網絡攝像頭之間進行切換。不幸的是,我嘗試了呼叫序列的多種組合,預覽只顯示了我使用的第一個設備。如何在使用CaptureElement/MediaCapture時切換網絡攝像頭?

這是我一直在努力做的事情:

XAML:

<CaptureElement 
    x:Name="captureElement" 
    Stretch="UniformToFill" /> 

C#:

MediaCapture mediaCapture; 
DeviceInformationCollection devices; 
int currentDevice = 0; 

private async void LayoutRoot_Tapped(object sender, Windows.UI.Xaml.Input.TappedEventArgs e) 
{ 
    if (devices != null) 
    { 
     currentDevice = (currentDevice + 1) % devices.Count; 
     InitializeWebCam(); 
    } 
} 

private async void InitializeWebCam() 
{ 
    if (devices == null) 
    { 
     devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture); 
     ListDeviceDetails(); 
    } 

    if (mediaCapture != null) 
    { 
     await mediaCapture.StopPreviewAsync(); 

     this.captureElement.Source = null; 
    } 

    mediaCapture = new MediaCapture(); 
    await mediaCapture.InitializeAsync(
     new MediaCaptureInitializationSettings 
     { 
      VideoDeviceId = devices[currentDevice].Id 
     }); 

    this.captureElement.Source = mediaCapture; 
    await mediaCapture.StartPreviewAsync(); 
} 

private void ListDeviceDetails() 
{ 
    int i = 0; 

    foreach (var device in devices) 
    { 
     Debug.WriteLine("* Device [{0}]", i++); 
     Debug.WriteLine("EnclosureLocation.InDock: " + device.EnclosureLocation.InDock); 
     Debug.WriteLine("EnclosureLocation.InLid: " + device.EnclosureLocation.InLid); 
     Debug.WriteLine("EnclosureLocation.Panel: " + device.EnclosureLocation.Panel); 
     Debug.WriteLine("Id: " + device.Id); 
     Debug.WriteLine("IsDefault: " + device.IsDefault); 
     Debug.WriteLine("IsEnabled: " + device.IsEnabled); 
     Debug.WriteLine("Name: " + device.Name); 
     Debug.WriteLine("IsDefault: " + device.IsDefault); 

     foreach (var property in device.Properties) 
     { 
      Debug.WriteLine(property.Key + ": " + property.Value); 
     } 
    } 
} 

好像它的工作,以在一旦切換到第二個攝像頭同時(低於10%的時間),然後在我回到第一個時保持全黑。

有時應用程序掛起後,我嘗試切換相機一次或兩次(停止響應輸入,它是停留在App.Run(),雖然攝像頭預覽不斷刷新)。

其他時候 - 它工作的方式,它顯示從第一設備預覽,但不爲其他一個,當我再回到第一個 - 它再次工作與它的罰款。

錯誤?

似乎有不是一個處置或未初始化方法的任何地方。這是我看到的性能(這是三星的Build 2011片):

* Device [0] 
EnclosureLocation.InDock: False 
EnclosureLocation.InLid: False 
EnclosureLocation.Panel: Front 
Id: \\?\USB#VID_2232&PID_1021&MI_00#7&2469C269&0&0000#{e5323777-f976-4f5b-9b55-b94699c46e44}\GLOBAL 
IsDefault: False 
IsEnabled: True 
Name: WebCam SC-20FHM11347N 
IsDefault: False 
System.ItemNameDisplay: WebCam SC-20FHM11347N 
System.Devices.DeviceInstanceId: USB\VID_2232&PID_1021&MI_00\7&2469C269&0&0000 
System.Devices.Icon: C:\Windows\System32\DDORes.dll,-2068 
System.Devices.InterfaceEnabled: True 
System.Devices.IsDefault: False 
* Device [1] 
EnclosureLocation.InDock: False 
EnclosureLocation.InLid: False 
EnclosureLocation.Panel: Back 
Id: \\?\USB#VID_2232&PID_1022&MI_00#7&27072759&0&0000#{e5323777-f976-4f5b-9b55-b94699c46e44}\GLOBAL 
IsDefault: False 
IsEnabled: True 
Name: WebCam SC-30H2L11449N 
IsDefault: False 
System.ItemNameDisplay: WebCam SC-30H2L11449N 
System.Devices.DeviceInstanceId: USB\VID_2232&PID_1022&MI_00\7&27072759&0&0000 
System.Devices.Icon: C:\Windows\System32\DDORes.dll,-2068 
System.Devices.InterfaceEnabled: True 
System.Devices.IsDefault: False 

回答

0

我認爲這個問題一定是與開發者預覽版本。在Consumer Preview中的3個網絡攝像頭之間切換時沒有問題。

2

我沒有平板電腦,和我很少有地鐵的經歷......但我有很多的異步編程經驗。你必須要知道的

的一件事是異步程序不符合國家發揮好。你本身沒有競爭條件,但你必須考慮重入性。在這樣的例子中,重入可能導致一種單線程「競態條件」。

如果我是對的,避免重新進入事件的一個簡單方法是有一個布爾型「重入守衛」變量(我在下面稱之爲switchingMedia)。試試這個:

MediaCapture mediaCapture; 
DeviceInformationCollection devices; 
int currentDevice = 0; 
bool switchingMedia = false; 

private async void LayoutRoot_Tapped(object sender, Windows.UI.Xaml.Input.TappedEventArgs e) 
{ 
    if (devices != null) 
    { 
     InitializeWebCam(); 
    } 
} 

private async void InitializeWebCam() 
{ 
    if (switchingMedia) 
     return; 
    switchingMedia = true; 

    if (devices == null) 
    { 
     devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture); 
     ListDeviceDetails(); 
    } 
    else 
    { 
     currentDevice = (currentDevice + 1) % devices.Count; 
    } 

    if (mediaCapture != null) 
    { 
     await mediaCapture.StopPreviewAsync(); 
     this.captureElement.Source = null; 
    } 

    mediaCapture = new MediaCapture(); 
    await mediaCapture.InitializeAsync(
     new MediaCaptureInitializationSettings 
     { 
      VideoDeviceId = devices[currentDevice].Id 
     }); 

    this.captureElement.Source = mediaCapture; 
    await mediaCapture.StartPreviewAsync(); 
    switchingMedia = false; 
} 

我也建議你有你的async方法返回Task而非void(除非他們是事件處理程序,當然)。這使他們可以組合。例如,如果InitializeWebCam返回Task,那麼你可以把重入後衛代碼在事件處理程序,而不是:

private async void LayoutRoot_Tapped(object sender, Windows.UI.Xaml.Input.TappedEventArgs e) 
{ 
    if (devices != null && !switchingMedia) 
    { 
     currentDevice = (currentDevice + 1) % devices.Count; 
     switchingMedia = true; 
     await InitializeWebCam(); 
     switchingMedia = false; 
    } 
} 

通過定義所有async方法默認返回Task,你有更多的組合性的選擇。

+0

謝謝你 - 它並沒有真正解決我的問題,但這些都是有用的技巧。 – 2012-02-04 03:58:25

0

獲得設備的所有列表後,嘗試像下面

var rearCamera = devices.FirstOrDefault(item => item.EnclosureLocation != null && 
                 item.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Back);