Hi all... i am Delpin, i love xamarin and also i am working xamarin . i am very interesting to get xamarin mvp. and also i wrote many article from c-sharp corner community contribution site.
any one reply to me.....
Hi all... i am Delpin, i love xamarin and also i am working xamarin . i am very interesting to get xamarin mvp. and also i wrote many article from c-sharp corner community contribution site.
any one reply to me.....
On view or on layout
Hi guys,
I have a page with table with 400+ items (4 columns, more than 100 rows). I've created it using Grid view, and there's a different image from local source in every cell. My problem is that it takes at least 10 seconds to open such page.
How to improve the performance? Should I use ListView instead? Will FFImageLoading improve the performance?
Thanks!
Hi ,
I have facing the below exception issue while using the rotator click one page and move on to next page this crash occur.
This happens randomly don't know why it comes
"Unhandled Exception:
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'Xamarin.Forms.Platform.Android.Platform+DefaultRenderer'."
Could you please provide any solution to override this
I found a bug deep in Xamarin.Forms 3.4 and wanted to diagnose it, so I forked the code but couldn't get it to compile etc.
The instructions on the Xamarin site for forking and creating a Nuget package to use in my project is very out of date.
I couldn't figure it out after an hour so had to give up.
Any new instructions on how to create a Nuget so we can debug/create PRs ?
Ian
Hi ,
I tried to work wih lottie , it works fine in ios but in android it does not show up .
I tried to add AnimationViewRenderer.Init() to main acitivity but it dosent work ! always dosnet know lottie .
does any one have this issue with lottie ?
Anyone having or ever had an issue with installing Xamarin Forms 3.0+ (or another version) and then the app starts crashing on the .init(..) line in the android activity on start up.
I am creating a blank project and updating XF to 3.0+ and this works fine, when I start adding packages and implement this in my activity in android I eventually get the exception and only works rolling back to XF's 2.5.
Any ideas how to debug this or preferably solve this issue. I am guessing this might be to do with a reference issue with one of my packages dependencies regarding Forms.
Error below:
Unhandled Exception:
System.TypeLoadException: Could not resolve type with token 010000c1 (from typeref, class/assembly Xamarin.Forms.Xaml.XamlResourceIdAttribute, Xamarin.Forms.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null)
Unhandled Exception:
Full error:
System.TypeLoadException: Could not resolve type with token 010000c1 (from typeref, class/assembly Xamarin.Forms.Xaml.XamlResourceIdAttribute, Xamarin.Forms.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null)
I am trying to create a ListView that bind a list of colors to a BoxView, it binds correctly, on item select the BoxView changes color, but the LisTView shows an empty cell, what am i doing wrong?
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness"
iOS="10, 20, 10, 0"
Android="10, 0"
WinPhone="10, 0" />
</ContentPage.Padding>
<StackLayout>
<ListView x:Name="listView"
SelectedItem="{Binding Source={x:Reference boxView},
Path=Color,
Mode=TwoWay}">
<ListView.ItemsSource>
<x:Array Type="{x:Type Color}">
<x:Static Member="Color.Aqua" />
<x:Static Member="Color.Black" />
<x:Static Member="Color.Blue" />
<x:Static Member="Color.Fuchsia" />
<x:Static Member="Color.Gray" />
<x:Static Member="Color.Green" />
<x:Static Member="Color.Lime" />
<x:Static Member="Color.Maroon" />
<Color>Navy</Color>
<Color>Olive</Color>
<Color>Pink</Color>
<Color>Purple</Color>
<Color>Red</Color>
<Color>Silver</Color>
<Color>Teal</Color>
<Color>White</Color>
<Color>Yellow</Color>
</x:Array>
</ListView.ItemsSource>
</ListView>
<BoxView x:Name="boxView"
Color="Lime"
HeightRequest="100" />
</StackLayout>
I also tried to add ítem template to the list view
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding .}"></Label>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate
Hi, I have a question about connecting to a database that runs on a server computer. When I access this database, I need to connect to a VPN and then use the connection string to connect to this database.
I use Visual Studio 2017, Xamarin, GenyMotion Version 3.0.0
ConnectionString
str = "Data Source = 172.16.172.12; Initial Catalog = SerBet; User ID = Project; Password = XX";
SqlConnection conn = new SqlConnection ();
conn.ConnectionString = str;
conn.Open ();
When I run the emulator, everything works the way it works. When I run my app on my phone, the connection will not take place.
catch (SqlException ex) = Snix_Connect (provider: SNI_PN7, error: 40-SNI_ERROR_40)
can someone give me an advice what could be the diference between emulator and real run from the android device?
Hello Guys,
I am constructing a Hybrid app using Xamarin, my App is Totally HTML + Css and JS, works fine(i am suing WebView Template Project), the app is just an Input form, the user can type text, select dates or check boxes etc, everything works fine, now i need to implement the functionality to attach an image(s) to the form and save the info into the DB, i would not like to save the image into the DB but save the DirPath and FileName as string. Later on the user could send the info of the Input Form (including the Images) to a Web Api Service . For now i just need to :
1.- Select the image from Gallery.
2.- Save the DirPath + The FileName.
Just keep in mind that i am not using Xamarin Forms, for that reason i need to trigger the functionality from an HTML button (this is not a problem for me ( i know how to do it) i just need the code to display the dialog box where the user can select an image from the Galley and later on just save the DirPath and FileName of the picture selected(could be more than one).
I really appreciate the help you can provide, KIND REGARDS.
Perhaps this is simply an uneducated question I am not sure. I use a number of Command Bindings similar to what is described here:
https://blog.xamarin.com/simplifying-events-with-commanding/
I like this approach quite a bit because it allows me to include virtually all code behind in the View Model. However, I am finding a few drawbacks that can sometimes cause problems.
1) When I bind a control in XAML the command (in this case "SquareRootCommand") does not refactor in Visual Studio with the attached view model. This causes problems when the command name gets renamed in the view model, leaving behind an orphaned control that no longer fires its intended command. Unfortunately, there are no compiler errors as I would have hoped. In fact it appears there not really any errors at run time either, Xamarin simply ignores the command.
2) Sometimes I forget to the declare the ICommand property in the view model as public. This again orphans the control because it can not reach the non public property. Again there are no compiler errors.
//Note the command is not public
ICommand SquareRootCommand { get; private set; }
Is this the intended behavior for Visual Studio or are there any plans to make the bound property/command in the XAML trigger a compiler error, similar to how an error is triggered if a XAML control EVENT is not properly found/wired up in the page code behind?
I understand the complexity that may exist since the design of the view model is not necessarily going to be defined the same way each time (it is not after all the code behind page file). However, is there an interface I should implement or a design practice that I should incorporate that may allow for more type safety in this regard?
I have a hundred or so clients connected to my server using .NetStandard websockets. Yet, I have one client on 4g data using an Android OnePlus 5t (T-Mobile data) that cannot connect. My server never even receives a call to begin the connection. Note, that he can connect using wifi data. Below are the things I have tried. Has anyone had a similar issue or know what could be the problem and how it might be solved. This is a TCP connection over port 1334.
i have developed to pick file form mobile, but need to pickup multpple file here is my code
try
{
FileData fileData = await CrossFilePicker.Current.PickFile();
if (fileData == null)
return; // user canceled file picking
string fileName = fileData.FileName;
string contents = System.Text.Encoding.UTF8.GetString(fileData.DataArray);
System.Console.WriteLine("File name chosen: " + fileName);
System.Console.WriteLine("File data: " + contents);
}
catch (Exception ex)
{
System.Console.WriteLine("Exception choosing file: " + ex.ToString());
}
need to know how i can select multiple files
Hello,
I am implementing UITableView with multiple sections.
Setting contentoffset programmatically when offset is out of the scope of contentsize, is making top cell or the last cell stuck at the center of the table view leaving blank space at top or bottom.
Now when scrolling up or down on table view make cells scroll to the proper position.
I have applied logic that whenever the user does some action like clicking on a button or gesture, few cells will hide. While hiding the cell I am making the height of those hiding cells 0 as well.
Good day
I am using Firebase Messaging to send/Receive Push Notification on Android.
I've got the following implementation which is triggering OnMessageReceived
twice on Android v 8.0, after rebooting the phone once, opening the app, rebooting the phone again and then sending myself a push notification.
Any ideas on what is causing this? I've looked online and found suggestions on removing any old GCM references which I have done already. The first time the app is built and deployed to the device, it doesn't happen and all subsequent push notifications seem fine. This just happens when the phone goes through the above mentioned reboot procedure. It may happen in other cases too but this has been my method to re-create the issue.
The App is compiled using
If any further information is required, please ask me.
The code is as follows:
MainActivity.cs
using System.Threading.Tasks;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Gms.Common;
using Android.OS;
using Android.Views;
using Plugin.Permissions;
using Android.Util;
using Android.Gms.Common.Apis;
using Android.Gms.Drive;
using Android.Runtime;
using System;
namespace App.Droid
{
[Activity(Label = "App", Icon = "@drawable/launch_icon", LaunchMode = LaunchMode.SingleTop, Theme = "@style/MyTheme", ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, GoogleApiClient.IConnectionCallbacks, GoogleApiClient.IOnConnectionFailedListener, IResultCallback
{
const string TAG = "MainActivity";
const int REQUEST_CODE_RESOLUTION = 3;
public static GoogleApiClient googleApiClient;
public static byte CurrentGoogleDriveState = 0x00;
internal static readonly string CHANNEL_ID = "default";
internal static readonly int NOTIFICATION_ID = 100;
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App("", ""));
IsPlayServicesAvailable();
CreateNotificationChannel();
}
void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
return;
}
var channel = new NotificationChannel(CHANNEL_ID,
"FCM Notifications",
NotificationImportance.Default)
{
Description = "Firebase Cloud Messages appear in this channel"
};
var notificationManager = (NotificationManager)GetSystemService(Android.Content.Context.NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
public bool IsPlayServicesAvailable()
{
int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.Success)
{
return false;
}
return true;
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto" package="--Redacted--" android:versionCode="--Redacted--" android:versionName="--Redacted--">
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="26" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-feature android:name="android.hardware.screen.landscape" />
<uses-feature android:name="android.hardware.wifi" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<application android:label="--Redacted--" android:icon="@drawable/logo_cropped" android:allowBackup="true" android:largeHeap="true">
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
<meta-data android:name="android.max_aspect" android:value="2.1" />
</application>
</manifest>
FirebaseRegistration.cs
using Android.App;
using Firebase.Iid;
using Android.Util;
using System;
using System.IO;
using Android.Content;
namespace App.Droid
{
[Service]
[IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
public class MyFirebaseIIDService : FirebaseInstanceIdService
{
const string TAG = "MyFirebaseIIDService";
public override void OnTokenRefresh()
{
base.OnTokenRefresh();
var refreshedToken = FirebaseInstanceId.Instance.Token;
Log.Debug(TAG, "Refreshed token: " + refreshedToken);
SendRegistrationToServer(refreshedToken);
}
/// <summary>
/// Sends the token to server.
/// </summary>
/// <param name="token">Token.</param>
void SendRegistrationToServer(string token)
{
// My code to send the push notification ID to our backend
}
}
}
FirebaseMessaging.cs
using System;
using System.Globalization;
using Android.App;
using Android.Content;
using System.Linq;
using Firebase.Messaging;
using System.Collections.Generic;
using System.Threading.Tasks;
using Android.OS;
using static Android.App.ActivityManager;
using Android.Support.V4.App;
namespace App.Droid
{
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class MyFirebaseMessagingService : FirebaseMessagingService
{
const string TAG = "MyFirebaseMsgService";
async public override void OnMessageReceived(RemoteMessage message)
{
base.OnMessageReceived(message);
Console.WriteLine("["+this.GetType().FullName+"]\t\t\t\t Push Notification Received! \n\n" + Newtonsoft.Json.JsonConvert.SerializeObject(message));
}
}
}
How to use resouce like this.
<OnPlatform
x:TypeArguments="x:String"
x:Key="SourceSansPro_Black">
<On
Platform="iOS"
Value="SourceSansPro-Black" />
<On
Platform="Android"
Value="SourceSansPro-Black.ttf#Source Sans Pro" />
</OnPlatform>
I have Javascript function which returns a collection of objects, how to get the collection on EvaluateJavascriptAsync call. It returns a string, and in my case it always returns null in C#. Any reference on this. TIA.
I'm using ZXingBarcodeImageView.... following is my code - the bar code is not using full width available. I'm not sure why ... any help is appreciated...
<ContentPage.Content>
<StackLayout Orientation="Vertical" >
<zxing:ZXingBarcodeImageView x:Name="BarCodeId"
BarcodeFormat="CODE_128"
HorizontalOptions="FillAndExpand" VerticalOptions="StartAndExpand" BarcodeValue="12345"
HeightRequest="150" MinimumHeightRequest="150" InputTransparent="True" >
<zxing:ZXingBarcodeImageView.BarcodeOptions>
<zxcm:EncodingOptions Height="150" PureBarcode="True" />
</zxing:ZXingBarcodeImageView.BarcodeOptions>
</zxing:ZXingBarcodeImageView>
</StackLayout>
</ContentPage.Content>
I have the following code, its not pretty but 'should' be functional....
Gets data from a UDP source, and then processes, eventually displays in AVSampleBufferDisplayLayer...at least that's the idea, I can successfully do the first part, its just the displaying bit that fails, I get a blank scree on the emulator???. I get non error messages and cannot figure out what is going on now.
Anybody that can help, Ill be truly gratefully.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using UIKit;
using CoreMedia;
using System.Collections.Generic;
using AVFoundation;
using CoreVideo;
using System.Runtime.InteropServices;
using ObjCRuntime;
namespace UDPTest.iOS
{
public partial class ViewController : UIViewController
{
UdpClient udpClient;
int Next;
int Previous;
int state;
int BufferPointer = 0;
byte[] videoData = new byte[1000000];
enum NALUnitType
{
unspecified = 0,
codedSlice = 1,
idr = 5,
sps = 7,
pps = 8,
}
byte[] SetUpStream = new byte[] {
0x00, 0x01, 0x01, 0x76, /* ...v */
0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x36, /* 00100006 */
0x30, 0x30, 0x30, 0x30, 0x35, 0x38, 0x30, 0x35, /* 00005805 */
0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x41, 0x75, /* 000001Au */
0x64, 0x69, 0x6f, 0x31, 0x30, 0x35, 0x30, 0x30, /* dio10500 */
0x30, 0x30, 0x30, 0x31, 0x56, 0x69, 0x64, 0x65, /* 0001Vide */
0x6f, 0x31, 0x30, 0x39, 0x30, 0x30, 0x30, 0x30, /* o1090000 */
0x30, 0x37, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, /* 07FrameS */
0x69, 0x7a, 0x65, 0x32, 0x38, 0x30, 0x30, 0x30, /* ize28000 */
0x66, 0x30, 0x30, 0x39, 0x30, 0x30, 0x30, 0x30, /* f0090000 */
0x30, 0x31, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, /* 01FrameR */
0x61, 0x74, 0x65, 0x66, 0x30, 0x37, 0x30, 0x30, /* atef0700 */
0x30, 0x30, 0x30, 0x33, 0x42, 0x69, 0x74, 0x52, /* 0003BitR */
0x61, 0x74, 0x65, 0x34, 0x30, 0x30 }; /* ate400 */
byte[] Describe = new byte[] {
0x00, 0x00, 0x00, 0x76, /* ...v */
0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x38, /* 00100008 */
0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x37, /* 00001007 */
0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x41, 0x6c, /* 000001Al */
0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x31 }; /* lInfo1 */
public ViewController(IntPtr handle) : base(handle)
{
}
AVSampleBufferDisplayLayer test;
public async override void ViewDidLoad()
{
base.ViewDidLoad();
udpClient = new UdpClient(3102);
state = 20;
Next = 1;
Previous = 0;
test = new AVSampleBufferDisplayLayer
{
Frame = View.Frame,
Bounds = View.Bounds,
BackgroundColor = UIColor.Black.CGColor
};
View.Layer.AddSublayer(test);
await UDPReceiveTest();
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
private async Task UDPReceiveTest()
{
while (true)
{
IPEndPoint Ip2 = new IPEndPoint(IPAddress.Parse("255.255.255.255"), 1000);
var UdpReceiveResult = await udpClient.ReceiveAsync();
ProcessPacket(UdpReceiveResult.Buffer);
}
}
private void UDPSendPacket(byte[] data)
{//192.168.1.1
IPEndPoint Ip2 = new IPEndPoint(IPAddress.Parse("255.255.255.255"), 1000);
var UdpReceiveResult = udpClient.Send(data, data.Length, Ip2);
}
private void ProcessPacket(byte[] Buffer)
{
if (Check_Announcement(Buffer) == true)
{
Console.WriteLine("Announcement");
string DescribeL = "\0\0\0v0010000800001007000001AllInfo1";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(DescribeL);
UDPSendPacket(buffer);
state = 2;
}
switch (state)
{
case 2: //Got Anouncement
{
if (Check_Description(Buffer) == true)
{
Console.WriteLine("Description Received");
byte[] buffer2 = new byte[] { 0x01, 0x00, 0x01, 0x76 };
UDPSendPacket(buffer2);
UDPSendPacket(SetUpStream);
state = 3;
}
break;
}
case 3: //Got All Info
{
if (Check_SetUpStreamAck(Buffer) == true)
{
Console.WriteLine("Got Setup Stream ACK");
byte[] buffer2 = new byte[] { 0x01, 0x01, 0x02, 0x76 };
UDPSendPacket(buffer2);
string s = System.Text.Encoding.UTF8.GetString(buffer2, 0, buffer2.Length);
state = 4;
}
break;
}
case 4: //Got Stream Settings
{
if (VideoDataIsRecognised(Buffer) == true)
{
int temp = Buffer[1] + 1;
byte[] next = BitConverter.GetBytes(temp);
byte[] ackb = new byte[] { 0x01, Buffer[1], next[0], 0x76 };
UDPSendPacket(ackb);
AppendVideoData(Buffer);
}
break;
}
default:
break;
}
}
private bool Check_Announcement(byte[] buffer)
{
if (buffer.Length == 32)
{
if (BitConverter.ToUInt32(buffer, 0) == 1752855916)
{
return true;
}
}
return false;
}
private bool Check_Description(byte[] buffer)
{
if (buffer.Length == 733)
{
string ss = System.Text.Encoding.UTF8.GetString(buffer, 26, 7);
if (0 == string.Compare(ss, "AllInfo"))
{
return true;
}
}
return false;
}
private bool Check_SetUpStreamAck(byte[] buffer)
{
if (buffer.Length == 30)
{
string ss = System.Text.Encoding.UTF8.GetString(buffer, 26, 4);
if (0 == string.Compare(ss, "Ret1"))
{
return true;
}
}
return false;
}
private bool VideoDataIsRecognised(byte[] buffer)
{
if (buffer.Length >= 90)
{
string ss = System.Text.Encoding.UTF8.GetString(buffer, 95, 4);
if (0 == string.Compare(ss, "Data"))
{
return true;
}
}
return false;
}
private void AppendVideoData(byte[] buffer)
{
if (buffer[99] == 0x00 && buffer[100] == 0x00 && buffer[101] == 0x00 && buffer[102] == 0x01) // 'Data' in bytes 95,96,97,98 so Ceck 99 onwards for NAL start Code
{
if (BufferPointer == 0)
{
// this is the first NAL, we will buffer this, and await the rest of the data in the remainder seuqnce,
// we will display when we get another sequence buffer tstarting with NAL
int copy = buffer.Length - 99;
Buffer.BlockCopy(buffer, 99, videoData, BufferPointer, copy);
BufferPointer = buffer.Length - 99;
}
else
{
// we already have data in our buffer, got our NAL so lets process what we have
ProcessVideo(videoData);
// Now store the new data we got and reset out pointer to show were gthering data
Buffer.BlockCopy(buffer, 99, videoData, 0, buffer.Length - 99);
BufferPointer = buffer.Length - 99;
}
}
else
{
// Doesnt start with a NAL start code, so either scrambled, or we are building a bigger buffer...
BufferPointer = BufferPointer + buffer.Length - 99;
Buffer.BlockCopy(buffer, 99, videoData, BufferPointer, buffer.Length - 99);
}
}
private bool CheckNALUStartCode(byte[] buffer)
{
if (buffer[0] == 0x00 && buffer[1] == 0x00 && buffer[2] == 0x00 && buffer[3] == 0x01)
{
return true;
}
return false;
}
private int StartCodeIndex(byte[] buffer, int from)
{
for (int i = from; i < buffer.Length - 5; i++)
{
if (buffer[i] == 0x00 && buffer[i + 1] == 0x00 && buffer[i + 2] == 0x00 && buffer[i + 3] == 0x01)
{
return i;
}
}
return -1;
}
CMBlockBuffer blockBuffer = null;
CMSampleBuffer sampleBuffer = null;
CMVideoFormatDescription formatDescription;
private void ProcessVideo(byte[] buffer)
{
// SPS, PPS, IDS
// BYTE: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 ........ etc
// DATA: 0 0 0 1 SPS D D D D D D D D D D D 0 0 0 1 PPS D D D D D D D D D D D 0 0 0 1 IDR D D D D D D ........ etc
// Coded Slide
// BYTE: 0 1 2 3 4 5 6 7 ........ etc
// DATA: 0 0 0 1 CDS D D D ........ etc
Console.WriteLine("Processing : " + BufferPointer.ToString());
NALUnitType naluType = (NALUnitType)(buffer[4] & 0x1F);
int spsRangeLower = 0;
int ppsRangeLower = 0;
int blockLength = 0;
if (formatDescription == null && naluType != NALUnitType.sps)
{
Console.WriteLine("Error: format Description is nil and frame does not start from SPS");
return;
}
if (naluType == NALUnitType.sps)
{
//sps should be 4 to 15, then 4 buffer bytes 0,0,0,1 ..so next NALU in byte 20, we DO NOT Include the code 0,0,0,1 (start code header) in the data
spsRangeLower = 4;
naluType = (NALUnitType)(buffer[20] & 0x1F);
}
if (naluType == NALUnitType.pps)
{
//pps should be 20 to 31
ppsRangeLower = 20;
naluType = (NALUnitType)(buffer[36] & 0x1F);
}
if (spsRangeLower != 0 && ppsRangeLower != 0) // Check we have SPS and PPS
{
int spsSize = 12;
int ppsSize = 12;
formatDescription = null;
byte[] param1 = new byte[spsSize];
byte[] param2 = new byte[ppsSize];
Array.Copy(buffer, spsRangeLower, param1, 0, spsSize);
Array.Copy(buffer, ppsRangeLower, param2, 0, ppsSize);
var props = new List<byte[]> { param1, param2 };
CMFormatDescriptionError Status = new CMFormatDescriptionError();
formatDescription = CMVideoFormatDescription.FromH264ParameterSets(props, 4, out Status);
if (formatDescription == null)
{
Console.WriteLine("Error: Can't create CMFormatDescription" + Status.ToString());
return;
}
}
if (naluType == NALUnitType.idr)
{
Console.WriteLine("Processing IDR");
int offset = 32; // starts at the header 0,0,0,1
blockLength = BufferPointer-offset;
byte[] data = new byte[blockLength];
Array.Copy(buffer, offset, data, 0, blockLength);
byte[] intBytes = BitConverter.GetBytes((UInt32)(blockLength - 4)); // dont include the header bytes, in the length
Array.Reverse(intBytes);
// now replace the 0,0,0,1 header bytes with the big endian length
Array.Copy(intBytes, data, 4);
CMBlockBufferError bbstatus = new CMBlockBufferError();
blockBuffer =CMBlockBuffer.FromMemoryBlock(data, 0, 0, out bbstatus);
if (blockBuffer == null)
{
Console.WriteLine("Error: Can't create CMBlockBuffer from IDR" + bbstatus.ToString());
return;
}
}
if (naluType == NALUnitType.codedSlice)
{
Console.WriteLine("Processing Code Slice");
// no offset coded slice always comes in its own UDP packet, with it NALU header as 0,1,2,3 bytes.... this gets replaces with length below.
blockLength = BufferPointer;
byte[] data = new byte[blockLength];
Array.Copy(buffer, 0, data, 0, blockLength);
byte[] intBytes = BitConverter.GetBytes((UInt32)(blockLength - 4)); // dont include the header bytes, in the length
Array.Reverse(intBytes);
// now replace the 0,0,0,1 header bytes with the big endian length
Array.Copy(intBytes, data, 4);
CMBlockBufferError bbstatus = new CMBlockBufferError();
blockBuffer = CMBlockBuffer.FromMemoryBlock(data, 0, 0, out bbstatus);
if (blockBuffer == null)
{
Console.WriteLine("Error: Can't create CMBlockBuffer from coded slice" + bbstatus.ToString());
return;
}
}
if (blockBuffer != null)
{
CMSampleBufferError status = new CMSampleBufferError();
nuint[] sampleSizeArray = new nuint[1];
sampleSizeArray[0] = (nuint)blockLength; //(nuint)BufferPointer;
CMSampleTimingInfo[] cmT = new CMSampleTimingInfo[1];
cmT[0].DecodeTimeStamp = sampleBuffer.DecodeTimeStamp;
cmT[0].PresentationTimeStamp = sampleBuffer.PresentationTimeStamp;
cmT[0].Duration = sampleBuffer.Duration;
sampleBuffer = CMSampleBuffer.CreateReady(blockBuffer, formatDescription, 1, cmT, sampleSizeArray, out status);
if (sampleBuffer == null)
{
Console.WriteLine("Error: Failed to create CMSampleBuffer");
return;
}
var dt = sampleBuffer.Duration;
var ts = sampleBuffer.DecodeTimeStamp;
var tp = sampleBuffer.PresentationTimeStamp;
Console.WriteLine("Duration: " + dt.Value);
//CMSampleBufferAttachmentSettings set = new CMSampleBufferAttachmentSettings(sampleBuffer.GetAttachments(CMAttachmentMode.ShouldNotPropagate));
//set.DisplayImmediately = true;
CMSampleBufferAttachmentSettings c = sampleBuffer.GetSampleAttachments(true)[0];
c.DisplayImmediately = true;
sampleBuffer.SetAttachments(c.Dictionary, CMAttachmentMode.ShouldNotPropagate);
if (test.ReadyForMoreMediaData)
{
test.EnqueueSampleBuffer(sampleBuffer);
test.SetNeedsDisplay();
CoreGraphics.CGImage tef = test.Contents;
if (tef == null)
{
Console.WriteLine("No Image Data?");
}
}
}
else
{
Console.WriteLine("Error: Reached end of the method without available blockBuffer");
return;
}
}
}
}
<ResourceDictionary.MergedWith>
<resources:Colors />
<resources:Fonts />
</ResourceDictionary.MergedWith>