Video recorder app in Windows Phone 8.1 - c#

I am going to write a Video Recorder app in Windows Phone 8.1 (RT).
I used the example provided in Windows Reference.
public sealed partial class CamcorderMainPage : Page
{
StatusBar StatusBarObject = Windows.UI.ViewManagement.StatusBar.GetForCurrentView();
string StatusBarHeader = "Firefly Moments";
MediaCaptureInitializationSettings _captureInitSettings;
List<Windows.Devices.Enumeration.DeviceInformation> _deviceList;
Windows.Media.MediaProperties.MediaEncodingProfile _profile;
Windows.Media.Capture.MediaCapture _mediaCapture;
bool _recording = false;
bool _previewing = false;
string NoCameraError = "No camera device is found ";
public CamcorderMainPage()
{
this.InitializeComponent();
this.Loaded += CamcorderMainPage_Loaded;
}
void CamcorderMainPage_Loaded(object sender, RoutedEventArgs e)
{
//throw new NotImplementedException();
EnumerateCameras();
}
private async void EnumerateCameras()
{
var devices = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(
Windows.Devices.Enumeration.DeviceClass.VideoCapture);
_deviceList = new List<Windows.Devices.Enumeration.DeviceInformation>();
// Add the devices to deviceList
if (devices.Count > 0)
{
for (var i = 0; i < devices.Count; i++)
{
_deviceList.Add(devices[i]);
}
InitCaptureSettings();
InitMediaCapture();
// rootPage.NotifyUser("Initialization complete.", NotifyType.StatusMessage);
}
else
{
StatusBarObject.ProgressIndicator.Text = NoCameraError;
//rootPage.NotifyUser("No camera device is found ", NotifyType.ErrorMessage);
}
}
private void InitCaptureSettings()
{
_captureInitSettings = null;
_captureInitSettings = new Windows.Media.Capture.MediaCaptureInitializationSettings();
_captureInitSettings.AudioDeviceId = "";
_captureInitSettings.VideoDeviceId = "";
_captureInitSettings.StreamingCaptureMode = Windows.Media.Capture.StreamingCaptureMode.AudioAndVideo;
_captureInitSettings.PhotoCaptureSource = Windows.Media.Capture.PhotoCaptureSource.VideoPreview;
if (_deviceList.Count > 0)
_captureInitSettings.VideoDeviceId = _deviceList[0].Id;
}
// Create a profile.
private void CreateProfile()
{
_profile = Windows.Media.MediaProperties.MediaEncodingProfile.CreateMp4(
Windows.Media.MediaProperties.VideoEncodingQuality.Qvga);
}
// Create and initialze the MediaCapture object.
public async void InitMediaCapture()
{
_mediaCapture = null;
_mediaCapture = new Windows.Media.Capture.MediaCapture();
// Set the MediaCapture to a variable in App.xaml.cs to handle suspension.
(App.Current as App).MediaCapture = _mediaCapture;
await _mediaCapture.InitializeAsync(_captureInitSettings);
CreateProfile();
}
// Start the video capture.
private async void StartMediaCaptureSession()
{
var storageFile = await Windows.Storage.KnownFolders.VideosLibrary.CreateFileAsync(
"cameraCapture.mp4", Windows.Storage.CreationCollisionOption.GenerateUniqueName);
await _mediaCapture.StartRecordToStorageFileAsync(_profile, storageFile);
_recording = true;
}
// Stop the video capture.
private async void StopMediaCaptureSession()
{
await _mediaCapture.StopRecordAsync();
_recording = false;
(App.Current as App).IsRecording = false;
}
private async void ShowFireFlyStatusBar()
{
//this will show the Status Bar
Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().SetDesiredBoundsMode(ApplicationViewBoundsMode.UseVisible);
StatusBarObject.ProgressIndicator.Text = StatusBarHeader;
StatusBarObject.ProgressIndicator.ProgressValue = 0;
StatusBarObject.ForegroundColor = Colors.MintCream;
StatusBarObject.BackgroundColor = Color.FromArgb(255, 166, 62, 59);
StatusBarObject.BackgroundOpacity = .6;
await StatusBarObject.ProgressIndicator.ShowAsync();
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached.
/// This parameter is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ShowFireFlyStatusBar();
}
private void Camcorder_StartCapture_Click(object sender, RoutedEventArgs e)
{
StartMediaCaptureSession();
}
private void Camcorder_StopCapture_Click(object sender, RoutedEventArgs e)
{
StopMediaCaptureSession();
}
}
Its working fine as I am getting the video file from Photos App .
Now how to enable live preview while recording in app? Which control to use for it?

You're looking for the CaptureElement. Once you add it to your XAML, connect it to your MediaCapture object and start preview like so:
PreviewControl.Source = _mediaCapture;
await _mediaCapture.StartPreviewAsync();
Have a look at the UniversalCameraSample posted on the Microsoft github page for more information. It targets Windows 10, but most of the patterns should work on 8/8.1 as well.

Related

How can I print a pdf document from Xamarin.Forms UWP?

I have a Xamarin.Forms application that supports only UWP. I cannot find a way to print a pdf document. Whatever I have seen on the web, for some reason doesn't work for me. E.g. I tried
https://www.syncfusion.com/kb/8767/how-to-print-pdf-documents-in-xamarin-forms-platform
It lets me print, but the preview in the print dialog never shows up, and the progress indicator just keeps rotating forever.
I also tried http://zawayasoft.com/2018/03/13/uwp-print-pdf-files-silently-without-print-dialog/
This gives me errors that I cannot fix.
So I wonder if somebody can suggest something else that would actually work. Maybe something newer than what I have tried (I use VS 2017). Printing without the printing dialog would be preferable.
Thank you in advance.
I used a very dirty hack to do that!
What I had to do was to try to print the image version of the pdf (I did the conversion in backend) and then used the following DependencyInjection:
Inside my Print class in UWP project:
class Print : IPrint
{
void IPrint.Print(byte[] content)
{
Print_UWP printing = new Print_UWP();
printing.PrintUWpAsync(content);
}
}
and the class responsible for printing in uwp:
public class Print_UWP
{
PrintManager printmgr = PrintManager.GetForCurrentView();
PrintDocument PrintDoc = null;
PrintDocument printDoc;
PrintTask Task = null;
Windows.UI.Xaml.Controls.Image ViewToPrint = new Windows.UI.Xaml.Controls.Image();
public Print_UWP()
{
printmgr.PrintTaskRequested += Printmgr_PrintTaskRequested;
}
public async void PrintUWpAsync(byte[] imageData)
{
int i = 0;
while (i < 5)
{
try
{
BitmapImage biSource = new BitmapImage();
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
await stream.WriteAsync(imageData.AsBuffer());
stream.Seek(0);
await biSource.SetSourceAsync(stream);
}
ViewToPrint.Source = biSource;
if (PrintDoc != null)
{
printDoc.GetPreviewPage -= PrintDoc_GetPreviewPage;
printDoc.Paginate -= PrintDoc_Paginate;
printDoc.AddPages -= PrintDoc_AddPages;
}
this.printDoc = new PrintDocument();
try
{
printDoc.GetPreviewPage += PrintDoc_GetPreviewPage;
printDoc.Paginate += PrintDoc_Paginate;
printDoc.AddPages += PrintDoc_AddPages;
bool showprint = await PrintManager.ShowPrintUIAsync();
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
}
// printmgr = null;
// printDoc = null;
// Task = null;
PrintDoc = null;
GC.Collect();
printmgr.PrintTaskRequested -= Printmgr_PrintTaskRequested;
break;
}
catch (Exception e)
{
i++;
}
}
}
private void Printmgr_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)
{
var deff = args.Request.GetDeferral();
Task = args.Request.CreatePrintTask("Invoice", OnPrintTaskSourceRequested);
deff.Complete();
}
async void OnPrintTaskSourceRequested(PrintTaskSourceRequestedArgs args)
{
var def = args.GetDeferral();
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
args.SetSource(printDoc.DocumentSource);
});
def.Complete();
}
private void PrintDoc_AddPages(object sender, AddPagesEventArgs e)
{
printDoc.AddPage(ViewToPrint);
printDoc.AddPagesComplete();
}
private void PrintDoc_Paginate(object sender, PaginateEventArgs e)
{
PrintTaskOptions opt = Task.Options;
printDoc.SetPreviewPageCount(1, PreviewPageCountType.Final);
}
private void PrintDoc_GetPreviewPage(object sender, GetPreviewPageEventArgs e)
{
printDoc.SetPreviewPage(e.PageNumber, ViewToPrint);
}
}
Please note that this is not a perfect solution and sometimes it crashes without actually being able to trace the exception (which is really strange) so I am sure there must be better answers even though it does the job.

Disable barcode scanner on preview window closing

When I close the preview window of my BarcodeScanner the webcam stay active and I want to prevent that because it's kind of weird to see that the camera is still on and that you can still scan some barcode even if I close the preview.
I can't figure out how to disable the BarcodeScanner when I close the preview window.
Here's my 'BarcodeScanner' code :
private async Task<bool> ClaimScanner()
{
bool res = false;
string selector = BarcodeScanner.GetDeviceSelector();
DeviceInformationCollection deviceCollection = await DeviceInformation.FindAllAsync(selector);
if(scanner == null)
scanner = await BarcodeScanner.FromIdAsync(deviceCollection[0].Id);
if (scanner != null)
{
if(claimedBarcodeScanner == null)
claimedBarcodeScanner = await scanner.ClaimScannerAsync();
if (claimedBarcodeScanner != null)
{
claimedBarcodeScanner.DataReceived += ClaimedBarcodeScanner_DataReceivedAsync;
claimedBarcodeScanner.ReleaseDeviceRequested += ClaimedBarcodeScanner_ReleaseDeviceRequested;
claimedBarcodeScanner.IsDecodeDataEnabled = true;
claimedBarcodeScanner.IsDisabledOnDataReceived = true;
await claimedBarcodeScanner.EnableAsync();
res = true;
Debug.WriteLine("Barcode Scanner claimed");
}
}
antispam = false;
return res;
}
public async void ScanBarcodeAsync()
{
if(claimedBarcodeScanner == null && !antispam)
{
antispam = true;
await ClaimScanner();
}
if(claimedBarcodeScanner != null)
{
await claimedBarcodeScanner.ShowVideoPreviewAsync();
await claimedBarcodeScanner.StartSoftwareTriggerAsync();
claimedBarcodeScanner = null;
}
}
private async void ClaimedBarcodeScanner_DataReceivedAsync(ClaimedBarcodeScanner sender, BarcodeScannerDataReceivedEventArgs args)
{
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
if (currentDataContext != null && currentDataContext is Scannable)
{
Debug.WriteLine(CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, args.Report.ScanDataLabel));
Scannable obj = (Scannable)currentDataContext;
obj.NumSerie = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, args.Report.ScanDataLabel);
}
}
);
}
void ClaimedBarcodeScanner_ReleaseDeviceRequested(object sender, ClaimedBarcodeScanner e)
{
// always retain the device
e.RetainDevice();
}
EDIT : I used the library indicated by Microsoft provided by Digimarc : https://learn.microsoft.com/en-us/windows/uwp/devices-sensors/pos-camerabarcode
Disable barcode scanner on preview window closing
ClaimedBarcodeScanner has StopSoftwareTriggerAsync method, if you want to disable barcode scanner on preview window closing, you just invoke StopSoftwareTriggerAsync method after HideVideoPreview.
private async void HidePreviewButton_Click(object sender, RoutedEventArgs e)
{
claimedScanner?.HideVideoPreview();
await claimedScanner?.StopSoftwareTriggerAsync();
}

How can i extract frames from video using directshowlib-2005?

With this code i can play video files from my hard disk and show the video in pictureBox1. But i wonder how can i save all the frames of the video to images files on the hard disk ? While playing the video or without playing i need somehow to extract the frames and save them.
This is my used code so far:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
IGraphBuilder m_graphBuilder = null;
IMediaControl m_mediaCtrl = null;
IMediaEventEx m_mediaEvt = null;
IMediaPosition m_mediaPos = null;
IMediaSeeking m_mediaSeeking = null;
public Form1()
{
InitializeComponent();
}
void InitInterfaces()
{
try
{
m_graphBuilder = (IGraphBuilder)new FilterGraph();
m_mediaCtrl = (IMediaControl)m_graphBuilder;
m_mediaEvt = (IMediaEventEx)m_graphBuilder;
m_mediaPos = (IMediaPosition)m_graphBuilder;
m_mediaSeeking = (IMediaSeeking)m_graphBuilder;
}
catch (Exception)
{
MessageBox.Show("Couldn't start directshow graph");
}
}
void CloseInterfaces()
{
if (m_mediaCtrl != null)
{
m_mediaCtrl.StopWhenReady();
}
m_mediaCtrl = null;
m_mediaEvt = null;
m_mediaPos = null;
m_mediaSeeking = null;
if (m_graphBuilder != null)
Marshal.ReleaseComObject(this.m_graphBuilder);
m_graphBuilder = null;
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void SetuupVideoRenderer()
{
IBaseFilter vmrFilter = null;
vmrFilter = (IBaseFilter)new VideoMixingRenderer();
m_graphBuilder.AddFilter(vmrFilter, "Video Renderer");
IVMRFilterConfig FilterConfig = (IVMRFilterConfig)vmrFilter;
FilterConfig.SetRenderingMode(VMRMode.Windowless);
IVMRWindowlessControl windowlessCtrl = (IVMRWindowlessControl)vmrFilter;
windowlessCtrl.SetVideoClippingWindow(this.pictureBox1.Handle);
windowlessCtrl.SetVideoPosition(null, DsRect.FromRectangle(pictureBox1.ClientRectangle));
windowlessCtrl.SetAspectRatioMode(VMRAspectRatioMode.LetterBox);
}
private void buttonLoad_Click(object sender, EventArgs e)
{
openFileDialog1.Filter = "All Files (*.*)|*.*|mp4 (*.mp4)|*.mp4|mov (*.mov)|*.mov||";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
CloseInterfaces();
InitInterfaces();
SetuupVideoRenderer();
m_graphBuilder.RenderFile(openFileDialog1.FileName, null);
textBoxDur.Text = ( getDuration() * 0.0000001).ToString();
m_mediaCtrl.Run();
timer1.Enabled = true;
}
}
private void GetPosition(out long CurrentPos,out long StopPos)
{
m_mediaSeeking.GetPositions(out CurrentPos, out StopPos);
}
private long getDuration()
{
long duration;
m_mediaSeeking.GetDuration(out duration);
return duration;
}
private void SetPos(double fPos)
{
DsLong startPosition = (DsLong)(10000000 * fPos);
m_mediaSeeking.SetPositions(startPosition, AMSeekingSeekingFlags.AbsolutePositioning, null, AMSeekingSeekingFlags.NoPositioning);
}
private void buttonPause_Click(object sender, EventArgs e)
{
m_mediaCtrl.Pause();
}
private void buttonPlay_Click(object sender, EventArgs e)
{
m_mediaCtrl.Run();
}
private void OnVideoCompleted()
{
MessageBox.Show("Video Playback Completed");
}
private void timer1_Tick(object sender, EventArgs e)
{
long iCurPos, iStopPos;
GetPosition(out iCurPos, out iStopPos);
if (iCurPos >= iStopPos)
{
timer1.Enabled = false;
OnVideoCompleted();
return;
}
textBoxCurPos.Text = (iCurPos * 0.0000001 ).ToString();
}
private void buttonGo_Click(object sender, EventArgs e)
{
SetPos(Convert.ToDouble(textBoxNewPos.Text));
timer1.Enabled = true;
}
}
}
I think this is excatly what you are looking for:
extract frames of a video
Have a look as well at this SO question and the links provided on this webpage.
The easiest way to do it is indeed using an FFMPEG, since its alredy includes some of the most common codecs (if you dont mind extra 30+Mb added to your app). As for wrappers, i used AForge wrapper in the past and really liked it, because of how simple it is to work with. Here is an example from its docs:
// create instance of video reader
VideoFileReader reader = new VideoFileReader();
// open video file
reader.Open( "test.avi");
// read 100 video frames out of it
for ( int i = 0; i < 100; i++)
{
Bitmap videoFrame = reader.ReadVideoFrame();
videoFrame.Save(i + ".bmp")
// dispose the frame when it is no longer required
videoFrame.Dispose( );
}
reader.Close();

Previous Page state lost on back key press

I am creating a Windows Phone 8.1 Universal App. There are some screens on my app. On the first screen, i am navigate my screen to second screen. When i press hardware back button on second screen. My previous page state lost.
I am unable to rectify where was the problem. Here is the code below:
Screen 1 Code
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.navigationHelper.OnNavigatedTo(e);
this.NavigationCacheMode = NavigationCacheMode.Enabled;
if (e.NavigationMode == NavigationMode.New)
{
BindQuickDateComboBox();
if (Frame.BackStack.Count > 0)
{
var lastPage = Frame.BackStack.Last().SourcePageType;
if (lastPage != null && lastPage.FullName == "Cryoserver.AppLogin")
{
Frame.BackStack.Clear();
}
}
}
}
async private void appBarSearch_Click(object sender, RoutedEventArgs e)
{
try
{
if (IsValidateForm())
{
ProgressBar.IsVisible = true;
cmdBarSearch.IsEnabled = false;
if (await conn.Table<SearchQuery>().CountAsync() > 0)
{
await conn.DropTableAsync<SearchQuery>();
await conn.CreateTableAsync<SearchQuery>();
}
var searchTerms = new SearchQuery();
if (Convert.ToString(cmbQuickDate.SelectedItem) != "Any Date")
{
searchTerms.FromDate = pickerFromDate.Date.ToString("d MMM yyyy");
searchTerms.FromTime = pickerFromTime.Time.ToString();
searchTerms.ToDate = pickerToDate.Date.ToString("d MMM yyyy");
searchTerms.ToTime = pickerToTime.Time.ToString();
}
searchTerms.SearchKeywords = txtKeywords.Text;
searchTerms.Parties = txtParties.Text;
searchTerms.Contributer = txtFrom.Text;
searchTerms.Viewer = txtTo.Text;
searchTerms.AttachmentName = txtAttName.Text;
searchTerms.AttachmentKeywords = txtAttKeywords.Text;
searchTerms.SearchReason = txtSearchReason.Text;
searchTerms.IsHighLight = "false";
await conn.InsertAsync(searchTerms);
object resultMails = await SearchEmailArchive();
if (!String.IsNullOrEmpty(Convert.ToString(resultMails)))
{
GlobalInfo.SelectedRow = -1;
GlobalInfo.SearchPageIndex = -1;
GlobalInfo.IsFindKeyword = false;
var archiveMails = JsonConvert.DeserializeObject<SearchResult>(resultMails.ToString());
Frame.Navigate(typeof(MailList), archiveMails);
}
ProgressBar.IsVisible = false;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
ProgressBar.IsVisible = false;
}
cmdBarSearch.IsEnabled = true;
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
}
Screen 2
I too used this code in second screen and also after removing this code. But it didn't work for me. Still the same problem.
void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
if (Frame.CanGoBack)
{
e.Handled = true;
Frame.GoBack();
}
}
Screen 1 state is Blank and behaves as a freshly loaded screen. Why?
Any help would be much appreciated.
I would try setting NavigationCacheMode="Required" in the constructor/XAML instead.

Get image frames while recording video

I am creating an app which sampling photos while recording video.
Is there any event which I can subscribe to, to get a frame each x time?
In android there is a method OnPreviewCallback (or something like this)
You would have to use PhotoCamera class
PhotoCamera class contains a method GetPreviewBufferArgb32 to get the preview frame into a byte array for furthur manipulations.
so, for say 5 frames per second you would need to make a timer and on timers tick you would have to call the method.
Refer these links, these would help you a lot
http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202956(v=vs.105).aspx
http://msdn.microsoft.com/en-us/magazine/hh708750.aspx
http://msdn.microsoft.com/en-US/library/windowsphone/develop/microsoft.devices.photocamera(v=vs.105).aspx
I used the code below for one of my projects(QrCode scanning)
private static readonly ManualResetEvent _pauseFramesEvent = new ManualResetEvent(true);
private PhotoCamera _cam;
private Thread _yFramesThread;
private Dictionary<object, object> _hintDictionary;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this._cam = new PhotoCamera();
this._cam.Initialized += _cam_Initialized;
this._pumpYFrames = true;
this._isScanning = true;
}
CreateStandByTimer();
this._yFramesThread = new Thread((PumpYFrames));
this._yFramesThread.Start();
base.OnNavigatedTo(e);
}
private void PumpYFrames()
{
var array = new byte[307200];
while (_pumpYFrames)
{
_pauseFramesEvent.WaitOne();
if (this._isScanning)
{
bool flag;
try
{
this._cam.GetPreviewBufferY(array);
flag = true;
}
catch
{
flag = false;
}
if (flag)
{
var source = new RGBLuminanceSource(array, 640, 480, false);
var binarizer = new HybridBinarizer(source);
var image = new BinaryBitmap(binarizer);
Reader reader = new QRCodeReader();
try
{
var results = reader.decode(image, _hintDictionary);
ProcessScan(results);
}
catch (Exception ex)
{//catch logic
}
}
}
}
}

Categories