Android Camera Callback Buffer Empty - c#

I am having a problem with the camera CallBack Buffer. The camera adds 4 new callbackbuffers, and also associates the byte Array to a dictionary mBytesToByteBuffer with the form (Byte[], ByteBuffer). I believe the problem lies with the fact the dictionary never updates its keys to the most recent frame. Leading to comparisons with current frame data failing. And the code not progressing past that point.
I have looked through the google example I have been working through, and it seems that they do not update their mBytesToByteBuffer at all, but that it seems to work.
From having looked at the source code for both AddCallbackBuffer and SetPreviewCallbackWithBuffer, it seems that they do not do anything with the byte arrays passed to them.
Declaration of mBytesToByteBuffer
public ConcurrentDictionary<byte[], ByteBuffer> mBytesToByteBuffer = new ConcurrentDictionary<byte[], ByteBuffer>();
Adding the CallbackBuffers:
camera.AddCallbackBuffer(createPreviewBuffer(mPreviewSize));
camera.AddCallbackBuffer(createPreviewBuffer(mPreviewSize));
camera.AddCallbackBuffer(createPreviewBuffer(mPreviewSize));
camera.AddCallbackBuffer(createPreviewBuffer(mPreviewSize));
camera.SetPreviewCallbackWithBuffer(new CameraPreviewCallback(this));
The dictionary mBytesToByteBuffer contains the correct size of byteArray, however this is never populated.
The Byte Buffer Dictionary is created here.
private byte[] createPreviewBuffer(Size previewSize)
{
int bitsPerPixel = ImageFormat.GetBitsPerPixel(ImageFormatType.Nv21);
long sizeInBits = previewSize.Height * previewSize.Width * bitsPerPixel;
int bufferSize = (int)System.Math.Ceiling(sizeInBits / 8.0d) + 1;
byte[] byteArray = new byte[bufferSize];
ByteBuffer buffer = ByteBuffer.Wrap(byteArray);
if (!buffer.HasArray)
{
throw new IllegalStateException("Failed to create valid buffer for camera source.");
}
mBytesToByteBuffer[byteArray] = buffer; //(byteArray, buffer);
return byteArray;
}
The callBackBuffer is called here through mBytesToByteBuffer
public void setNextFrame(byte[] data, Android.Hardware.Camera camera)
{
lock (mLock)
{
if (mPendingFrameData != null)
{
camera.AddCallbackBuffer(mPendingFrameData.ToArray<System.Byte>());
mPendingFrameData = null;
}
if (!cameraSource.mBytesToByteBuffer.ContainsKey(data))
{
Log.Debug(TAG, "Skipping Frame, Could not Find ByteBuffer Associated with image");
return;
}
mPendingTimeMillis = SystemClock.ElapsedRealtime() - mStartTimeMillis;
mPendingFrameId++;
mPendingFrameData = cameraSource.mBytesToByteBuffer[data];
Monitor.PulseAll(mLock);
}
}
But the code never gets past
if(!cameraSource.mBytesToByteBuffer.containsKey(data)
Data is fully populated.
CameraPreviewCallback:
private class CameraPreviewCallback : Java.Lang.Object, Android.Hardware.Camera.IPreviewCallback
{
CameraSource cameraSource;
public CameraPreviewCallback(CameraSource cs)
{
cameraSource = cs;
}
public void OnPreviewFrame(byte[] data, Android.Hardware.Camera camera)
{
cameraSource.mFrameProcessor.setNextFrame(data, camera);
}
}
I have been working through the Google Vison Example Camera Source
My Full Camera Source

Related

Can MemoryPool<byte>.Rent(int minBufferSize ) capable of returning a IMemoryOwner<byte> bigger than asked?

I understand that the internal buffer used by IMemoryOwner<byte>.Memory can be larger than asked. But, is IMemoryOwner<byte>.Memory.Length defined with what I asked or with the size of the internal buffer ? The document seems not accurate enough.
Let's take a look.
MemoryPool<T>.Rent is abstract, so we'll go looking for an implementation. ArrayMemoryPool<T>.Rent looks like a good, representative candidate. That implementation looks like this:
public sealed override IMemoryOwner<T> Rent(int minimumBufferSize = -1)
{
if (minimumBufferSize == -1)
minimumBufferSize = 1 + (4095 / Unsafe.SizeOf<T>());
else if (((uint)minimumBufferSize) > MaximumBufferSize)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.minimumBufferSize);
return new ArrayMemoryPoolBuffer(minimumBufferSize);
}
Let's chase that into ArrayMemoryPoolBuffer:
private sealed class ArrayMemoryPoolBuffer : IMemoryOwner<T>
{
private T[]? _array;
public ArrayMemoryPoolBuffer(int size)
{
_array = ArrayPool<T>.Shared.Rent(size);
}
public Memory<T> Memory
{
get
{
T[]? array = _array;
if (array == null)
{
ThrowHelper.ThrowObjectDisposedException_ArrayMemoryPoolBuffer();
}
return new Memory<T>(array);
}
}
public void Dispose()
{
T[]? array = _array;
if (array != null)
{
_array = null;
ArrayPool<T>.Shared.Return(array);
}
}
}
The new Memory<T>(array) means that Memory<T>.Length will just be the size of the underlying array: we don't have any logic to have a smaller Memory<T> wrapping a larger array. So let's see if ArrayPool<T>.Shared.Rent gives us back an array of the correct size...
Again this is abstract, but we can find an implementation at ConfigurableArrayPool<T>. The meat of that method is:
int index = Utilities.SelectBucketIndex(minimumLength);
if (index < _buckets.Length)
{
// Search for an array starting at the 'index' bucket. If the bucket is empty, bump up to the
// next higher bucket and try that one, but only try at most a few buckets.
const int MaxBucketsToTry = 2;
int i = index;
do
{
// Attempt to rent from the bucket. If we get a buffer from it, return it.
buffer = _buckets[i].Rent();
if (buffer != null)
{
if (log.IsEnabled())
{
log.BufferRented(buffer.GetHashCode(), buffer.Length, Id, _buckets[i].Id);
}
return buffer;
}
}
while (++i < _buckets.Length && i != index + MaxBucketsToTry);
// The pool was exhausted for this buffer size. Allocate a new buffer with a size corresponding
// to the appropriate bucket.
buffer = new T[_buckets[index]._bufferLength];
}
else
{
// The request was for a size too large for the pool. Allocate an array of exactly the requested length.
// When it's returned to the pool, we'll simply throw it away.
buffer = new T[minimumLength];
}
We can see that the pool has multiple buckets, with each bucket containing arrays of a specified size. This method is finding the bucket of arrays which are just larger than the requested size; if that bucket is empty it goes looking at larger buckets. If it fails to find anything, it creates a new array with the bucket size; only if the requested size is larger than the pool can manage does it create an array of the exact requested size.
So it's very unlikely that the array underlying the Memory<T> has the requested size, and the construction of the Memory<T> does nothing to pretend that the Memory<T> is smaller than its underlying array.
The conclusion is that IMemoryOwner<byte>.Memory.Length can indeed be larger than requested.

lost of packages on UdpClient receiver

My application using UdpClient to receive images from some other machine.
Each image size is 951000 bytes and MTU limit is 1500 bytes.
So the sender application must use fragmentation ... and each sending package contain header that contain 2 int
total_number
current_number
The code receiving bytes .. .and this is very intensive bit rate because the video have new frame to send to my application every 30 milisecond ..
I found myself losing packages and i don't know how to do it different and not to lose packages.
Someone have any idea how to solve this ?
Is there any better way ?
this is the code
public class PackagePartial
{
public int total_count;
public int current_count; // first package is 1
public byte[] buffer;
public byte[] Serializable()
{
// make the Serialize
}
public static void DeSerializable(byte[] v)
{
total_count = ... ;
current_count = ...
buffer = ...
}
}
// the network layer
int lastPackIndex = 0;
List<byte> collection = new List<byte>();
while(true)
{
byte[] package = _clientListener.Receive(ref ep);
PackagePartial p = PackagePartial.DeSerializable(package);
// indication that i lost package
if(p.current_count - lastPackIndex != 1 )
{
collection.Clear();
lastPackIndex = 0
continue;
}
if(p.current_count == p.total_count)
{
// image Serialize and send it to the GUI layer as bitmap
Image img = ConvertBytesToImage(collection);
SendToGui(img);
collection.Clear();
lastPackIndex = 0
}
else
{
lastPackIndex = p.current_count
collection.AddRange(p.Buffer)
}
Don't deserialize each package to an intermediate class after recieve.
Create a List of byte arrays and stuff them all in there as they come in.
Once the other side finishes sending, look in the first one to find the total count and see if the List.Count matches the total count.
If it does, you have all of the packages, now you can reassemble the image, just disregard the headers, you don't need them anymore.
Since you don't need anything at this point but the data from each packet, assembling the image should be faster (no serialization to an intermediate class involved anymore).
This should minimize the processing required for each image.

Reading Serialized MFC CArray in C#

MFC CArray was Serialized and saved to a database. I need to read this data into a C# project. I am able to retrieve the data as byte[] from the database. I then write the byte[] to a MemoryStream. Now I need to read the data from the MemoryStream.
Someone has apparently solved this before, but did not write their solution.
http://social.msdn.microsoft.com/Forums/eu/csharpgeneral/thread/17393adc-1f1e-4e12-8975-527f42e5393e
I followed these projects in my attempt to solve the problem.
http://www.codeproject.com/Articles/32741/Implementing-MFC-Style-Serialization-in-NET-Part-1
http://www.codeproject.com/Articles/32742/Implementing-MFC-Style-Serialization-in-NET-Part-2
The first thing in the byte[] is the size of the array, and I can retrieve that with binaryReader.readInt32(). However, I cannot seem to get back the float values. If I try binaryReader.readSingle() or
public void Read(out float d) {
byte[] bytes = new byte[4];
reader.Read(bytes, m_Index, 4);
d = BitConverter.ToSingle(bytes, 0);
}
I do not get back the correct data. What am I missing?
EDIT Here is the C++ code that serializes the data
typedef CArray<float, float> FloatArray;
FloatArray floatArray;
// fill floatArray
CSharedFile memoryFile(GMEM_MOVEABLE | GMEM_ZEROINIT);
CArchive ar(&memoryFile, CArchive::store);
floatArray.Serialize(ar);
ar.Close();
EDIT 2
By reading backward, I was able to get all of the floats, and was also able to determine that the size for CArray is byte[2], or Int16. Does anyone know if this is always the case?
Using the codeproject articles above, here is a C# implementation of CArray which will allow you to deserialize a serialized MFC CArray.
// Deriving from the IMfcArchiveSerialization interface is not mandatory
public class CArray : IMfcArchiveSerialization {
public Int16 size;
public List<float> floatValues;
public CArray() {
floatValues = new List<float>();
}
virtual public void Serialize(MfcArchive ar) {
if(ar.IsStoring()) {
throw new NotImplementedException("MfcArchive can't store");
}
else {
// be sure to read in the order in which they were stored
ar.Read(out size);
for(int i = 0; i < size; i++) {
float floatValue;
ar.Read(out floatValue);
floatValues.Add(floatValue);
}
}
}
}

Having trouble with extension methods for byte arrays

I'm working with a device that sends back an image, and when I request an image, there is some undocumented information that comes before the image data. I was only able to realize this by looking through the binary data and identifying the image header information inside.
I originally had a normal method and converted it to an extension method. The original question here was related to the compiler complaining about not having Array as the first parameter (I had Byte[]), but it turns out that I had made an error and forgot to delete the first argument in the calling code. In other words, I used to have:
Byte[] new_buffer = RemoveUpToByteArray(buffer, new byte[] { 0x42, 0x4D });
and after changing to an extension method, I had erroneously used:
buffer.RemoveUpToByteArray( buffer, new byte[] { 0x42, 0x4D });
Anyhow, that's all fixed now because I realized my mistake as I was entering the code example into SO. However, I have a new problem that is simply lack of understanding of extension methods and reference vs. value types. Here's the code:
public static void RemoveFromByteArrayUntil(this Byte[] array, Byte[] until)
{
Debug.Assert(until.Count() > 0);
int num_header_bytes = until.Count();
int header_start_pos = 0; // the position of the header bytes, defined by [until]
byte first_header_byte = until[0];
while(header_start_pos != -1) {
header_start_pos = Array.IndexOf(array, first_header_byte, header_start_pos);
if(header_start_pos == -1)
break;
// if we get here, then we've found the first header byte, and we need to look
// for the next ones sequentially
for(int header_ctr=1; header_ctr<num_header_bytes; header_ctr++) {
// we're going to loop over each of the header bytes, but will
// bail out of this loop if there isn't a match
if(array[header_start_pos + header_ctr] != until[header_ctr]) {
// no match, so bail out. but before doing that, advance
// header_start_pos so the outer loop won't find the same
// occurrence of the first header byte over and over again
header_start_pos++;
break;
}
}
// if we get here, we've found the header!
// create a new byte array of the new size
int new_size = array.Count() - header_start_pos;
byte[] output_array = new byte[new_size];
Array.Copy(array, header_start_pos, output_array, 0, new_size);
// here is my problem -- I want to change what array points to, but
// when this code returns, array goes back to its original value, which
// leads me to believe that the first argument is passed by value.
array = output_array;
return;
}
// if we get here, we didn't find a header, so throw an exception
throw new HeaderNotInByteArrayException();
}
My problem now is that it looks like the first this argument to the extension method is passed by value. I want to reassign what array points to, but in this case, it looks like I'll have to just manipulate array's data instead.
Extension methods are static methods that only appear to be instance methods. You can consider the instance the extension method is working on to be read only (by value). Assigning to the instance method of byte[] that is the first parameter of your extension won't work. You won't be able to get away from assigning, but you could modify your extension then write your assignment like this:
buffer = buffer.RemoveUpToByteArray(header);
Make your extension return the byte array result, and don't try to assign to buffer within the extension. Your extension would then be something like this:
public static class MyExtensionMethods
{
public static byte[] RemoveUpToByteArray(this byte[] buffer, byte[] header)
{
byte[] result = buffer;
// your logic to remove header from result
return result;
}
}
I hope this helps.
EDIT:
The above is correct for value types only. If the type you are extending is a reference type, then you would not have an issue operating directly on the type like you are trying to do above. Sadly, a byte array is a struct, and thus derived from System.ValueType. Consider the following, which would be perfectly legal inside an extension, and would give the desired result:
public class MyBytes
{
public byte[] ByteArray { get; set; }
}
public static class MyExtensionMethods
{
// Notice the void return here...
public static void MyClassExtension(this MyBytes buffer, byte[] header)
{
buffer.ByteArray = header;
}
}
I am sorry that I do not know what specific problem you are encountering, or how to resolve it [certainly checking namespace is referenced and resolving any conflicts with similarly named methods is a start], but I did notice one or two oddities.
Consider the following sample solution,
using System.Linq;
namespace Sample.Extensions
{
public static class ByteExtensions
{
public static void RemoveHeader (this byte[] buffer, byte[] header)
{
// take first sequence of bytes, compare to header, if header
// is present, return only content
//
// NOTE: Take, SequenceEqual, and Skip are standard Linq extensions
if (buffer.Take (header.Length).SequenceEqual (header))
{
buffer = buffer.Skip (header.Length).ToArray ();
}
}
}
}
This compiles and runs in VS2010RC. To demonstrate usage,
using Sample.Extensions;
namespace Sample
{
class Program
{
static void Main (string[] args)
{
byte[] buffer = new byte[] { 00, 01, 02 };
byte[] header = new byte[] { 00, 01 };
buffer.RemoveHeader (header);
// hm, so everything compiles and runs, but buffer == { 00, 01, 02 }
}
}
}
So we will not receive a compile or run-time error but clearly it will not operate as intended. This is because extensions must still comply with standard method semantics, meaning parameters are passed by value. We cannot change buffer to point to our new array.
We can resolve this issue by rewriting our method to conventional function semantics,
public static byte[] RemoveHeaderFunction (this byte[] buffer, byte[] header)
{
byte[] stripped = null;
if (stripped.Take (header.Length).SequenceEqual (header))
{
stripped = stripped.Skip (header.Length).ToArray ();
}
else
{
stripped = buffer.ToArray ();
}
return stripped;
}
Now
using Sample.Extensions;
namespace Sample
{
class Program
{
static void Main (string[] args)
{
byte[] buffer = new byte[] { 00, 01, 02 };
byte[] header = new byte[] { 00, 01 };
// old way, buffer will still contain { 00, 01, 02 }
buffer.RemoveHeader (header);
// new way! as a function, we obtain new array of { 02 }
byte[] stripped = buffer.RemoveHeaderFunction (header);
}
}
}
Unfortunately, arrays are immutable value types [may be using these terms incorrectly]. The only way to modify your "array" in-place is to change the container to a mutable reference-type, like a List<byte>.
If you are really keen on "passing by ref", in-place, side-effect semantics, then one option may be the following
using System.Linq;
namespace Sample.Extensions
{
public static class ListExtensions
{
public static void RemoveHeader<T> (this List<T> list, List<T> header)
{
if (list.Take (header.Count).SequenceEqual (header))
{
list.RemoveRange (0, header.Count);
}
}
}
}
As for usage,
static void Main (string[] args)
{
byte[] buffer = new byte[] { 00, 01, 02 };
byte[] header = new byte[] { 00, 01 };
List<byte> bufferList = buffer.ToList ();
// in-place side-effect header removal
bufferList.RemoveHeader (header.ToList ());
}
Under the hood, List<T> is maintaining an array of type T. At certain thresholds, it is simply manipulating the underlying array and\or instantiating new arrays for us.
Hope this helps! :)

What is the equivalent of "ByteBuffer.flip" & "ByteBuffer.slice" in .NET?

I need to port code from Java to C#. In the Java code, the methods "ByteBuffer.flip()" and "ByteBuffer.slice" is used, and I don't know how to translate this.
I've read this question (An equivalent of javax.nio.Buffer.flip() in c#), but although an answer is given, I cannot figure how to apply it. According to Tom Hawtin, I should "Set the limit to the current position and then set the position to zero" in the underlying array. I am unsure as of how to change these values. (If you could explain the underlying logic, it would help me a lot :)
As for the ByteBuffer.slice, I have no clue on how to translate it.
EDIT: If it can be clearer with the actual code, I'll post it:
Java:
ByteBuffer buff;
buff.putShort((short) 0);
buff.put(customArray);
buff.flip();
buff.putShort((short) 0);
ByteBuffer b = buff.slice();
short size = (short) (customFunction(b) + 2);
buff.putShort(0, size);
buff.position(0).limit(size);
So far, my translation in C#.NET:
BinaryWriter b = new BinaryWriter(); //ByteBuffer buff;
b.Write((short)0); // buff.putShort((short) 0);
b.Write(paramStream.ToArray()); // buff.put(customArray);
b.BaseStream.SetLength(b.BaseStream.Position); // buff.flip; (not sure)
b.BaseStream.Position = 0; // buff.flip; too (not sure)
b.Write((short)0); // buff.putShort((short) 0)
??? // ByteBuffer b = buff.slice();
// Not done but I can do it, short size = (short) (customFunction(b) + 2);
??? // How do I write at a particular position?
??? // buff.position(0).limit(size); I don't know how to do this
Thank you!
EDIT: Changed b.BaseStream.SetLength(b.BaseStream.Length); to b.BaseStream.SetLength(b.BaseStream.Position);, based on the Java docs.
(See See http://java.sun.com/javase/6/docs/api/java/nio/ByteBuffer.html#slice%28%29 and http://java.sun.com/javase/6/docs/api/java/nio/Buffer.html#flip%28%29 for java's calls)
Flip is a quick way to reset the buffer. So for example
(pseudocode)
void flip()
{
Length = currentPos;
currentPos = 0;
}
Allows you to quickly setup the buffer you presumably just wrote to for reading from the beginning.
Update:
Splice is a bit trickier due to the requirement that "Changes to this buffer's content will be visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent". There unfortunately is no concept of a shared portion of buffer (that i know of - theres always using arrays, detailed below) without making your own class. The closest thing you could do is this:
Old Code:
ByteBuffer b = buff.slice();
New Code (assuming a List)
List<Byte> b= buff;
int bStart = buffPos; // buffPos is your way of tracking your mark
the downside to the code above is that there is no way for c# to hold the new starting point of the new buffer and still share it. You'll have to manually use the new starting point whenever you do anything, from for loops (for i=bStart;...) to indexing (newList[i + bStart]...)
Your other option is to do use Byte[] arrays instead, and do something like this:
Byte[] b = &buff[buffPos];
... however that requires unsafe operations to be enabled, and I cannot vouch for its saftey, due to the garbage collector and my avoidance of the "unsafe" features.
Outside of that, theres always making your own ByteBuffer class.
Untested, but if I understand the java bits correctly, this would give you an idea on how to implement.
public class ByteBuffer {
private int _Position;
private int _Capacity;
private byte[] _Buffer;
private int _Start;
private ByteBuffer(int capacity, int position, int start, byte[] buffer) {
_Capacity = capacity;
_Position = position;
_Start = start;
_Buffer = buffer;
}
public ByteBuffer(int capacity) : this(capacity, 0 , 0, new byte[capacity]) {
}
public void Write(byte item) {
if (_Position >= _Capacity) {
throw new InvalidOperationException();
}
_Buffer[_Start + _Position++] = item;
}
public byte Read() {
if (_Position >= _Capacity) {
throw new InvalidOperationException();
}
return _Buffer[_Start + _Position++];
}
public void Flip() {
_Capacity = _Position;
_Position = _Start;
}
public ByteBuffer Slice() {
return new ByteBuffer(_Capacity-_Position, 0, _Position, _Buffer);
}
}

Categories

Resources