public override void HandleMessage(Message msg) { if (msg.What == 100) { Message msg1 = new Message(); msg1.What = 200; msg1.Obj = ""; try { YuvImage image = (YuvImage)msg.Obj; if (image != null) { int[] stridelist = image.GetStrides(); TextResult[] text = barcodeReader.DecodeBuffer(image.GetYuvData(), previewWidth, previewHeight, stridelist[0], EnumImagePixelFormat.IpfNv21, ""); if (text != null && text.Length > 0) { for (int i = 0; i < text.Length; i++) { if (i == 0) { msg1.Obj = "Code[1]: " + text[0].BarcodeText; } else { msg1.Obj = msg1.Obj + "\n\n" + "Code[" + (i + 1) + "]: " + text[i].BarcodeText; } } } } } catch (BarcodeReaderException e) { msg1.Obj = ""; e.PrintStackTrace(); } isReady = true; myHandler.SendMessage(msg1); } else if (msg.What == 200) { tv_text.Text = msg.Obj.ToString(); //System.Console.WriteLine("end update UI"); } }
public void OnPreviewFrame(byte [] bytes, Android.Hardware.Camera camera) { if ((DateTime.Now - lastPreviewAnalysis).TotalMilliseconds < options.DelayBetweenAnalyzingFrames) { return; } try { var cameraParameters = camera.GetParameters(); var img = new YuvImage(bytes, ImageFormatType.Nv21, cameraParameters.PreviewSize.Width, cameraParameters.PreviewSize.Height, null); if (barcodeReader == null) { barcodeReader = new BarcodeReader(null, null, null, (p, w, h, f) => new PlanarYUVLuminanceSource(p, w, h, 0, 0, w, h, false)); //new PlanarYUVLuminanceSource(p, w, h, dataRect.Left, dataRect.Top, dataRect.Width(), dataRect.Height(), false)) if (this.options.TryHarder.HasValue) { barcodeReader.Options.TryHarder = this.options.TryHarder.Value; } if (this.options.PureBarcode.HasValue) { barcodeReader.Options.PureBarcode = this.options.PureBarcode.Value; } if (!string.IsNullOrEmpty(this.options.CharacterSet)) { barcodeReader.Options.CharacterSet = this.options.CharacterSet; } if (this.options.TryInverted.HasValue) { barcodeReader.TryInverted = this.options.TryInverted.Value; } if (this.options.PossibleFormats != null && this.options.PossibleFormats.Count > 0) { barcodeReader.Options.PossibleFormats = new List <BarcodeFormat>(); foreach (var pf in this.options.PossibleFormats) { barcodeReader.Options.PossibleFormats.Add(pf); } } //Always autorotate on android barcodeReader.AutoRotate = true; } //Try and decode the result var result = barcodeReader.Decode(img.GetYuvData(), img.Width, img.Height, RGBLuminanceSource.BitmapFormat.Unknown); lastPreviewAnalysis = DateTime.Now; if (result == null || string.IsNullOrEmpty(result.Text)) { return; } Android.Util.Log.Debug("ZXing.Mobile", "Barcode Found: " + result.Text); ShutdownCamera(); callback(result); } catch (ReaderException) { Android.Util.Log.Debug("ZXing.Mobile", "No barcode Found"); // ignore this exception; it happens every time there is a failed scan } catch (Exception) { // TODO: this one is unexpected.. log or otherwise handle it throw; } }
private void EncodeMux() { int TIMEOUT_USEC = 10000; ByteBuffer[] encoderInputBuffers = _Encoder.GetInputBuffers(); bool inputDone = false; int frameIndex = 0; try { while (true) { if (!inputDone) { int inputBufIndex = _Encoder.DequeueInputBuffer(TIMEOUT_USEC); if (inputBufIndex >= 0) { long ptsUsec = computePresentationTime(frameIndex); if (frameIndex == _ByteBuffers.Count) { // Send an empty frame with the end-of-stream flag set. If we set EOS on a frame with data, that frame data will be ignored, and the output will be short one frame. _Encoder.QueueInputBuffer(inputBufIndex, 0, 0, ptsUsec, MediaCodec.BufferFlagEndOfStream); inputDone = true; Log.Info(TAG, "sent input EOS (with zero-length frame)"); } else { Log.Info(TAG, string.Format("Adding _ByteBuffers image index {0} to encoder", frameIndex)); ByteBuffer inputBuf = encoderInputBuffers[inputBufIndex]; var imagedata = _ByteBuffers[frameIndex]; int chunkSize = 0; if (imagedata == null) { Log.Warn(TAG, string.Format("Adding _ByteBuffers image index {0} to encoder", frameIndex)); } else { //old way don't need to do this anymore. //Bitmap b = GetBitmap(imagedata); //byte[] yuv = new byte[b.Width * b.Height * 3 / 2]; //int[] argb = new int[b.Width * b.Height]; //b.GetPixels(argb, 0, b.Width, 0, 0, b.Width, b.Height); //encodeYUV420SP(yuv, argb, b.Width, b.Height); //b.Recycle(); //old way don't need to do this anymore? //int[] argb = new int[imagedata.Width * imagedata.Height]; //imagedata.GetPixels(argb, 0, imagedata.Width, 0, 0, imagedata.Width, imagedata.Height); //byte[] yuv = new byte[imagedata.Width * imagedata.Height * 3 / 2]; //encodeYUV420SP(yuv, argb, imagedata.Width, imagedata.Height); //YuvImage yuv = GetYUVImage(imagedata); //byte[] decomB = Utils.DecompressFast(imagedata); //var yuv = new YuvImage(decomB, _CameraColorFormat, _Width, _Height, null); //Bitmap b = BitmapFactory.DecodeByteArray(imagedata, 0, imagedata.Length); //byte[] yuv = new byte[b.Width * b.Height * 3 / 2]; //int[] argb = new int[b.Width * b.Height]; //b.GetPixels(argb, 0, b.Width, 0, 0, b.Width, b.Height); //encodeYUV420SP(yuv, argb, b.Width, b.Height); Bitmap b = BitmapFactory.DecodeByteArray(imagedata, 0, imagedata.Length); byte[] yuv = new byte[b.Width * b.Height * 3 / 2]; int[] argb = new int[b.Width * b.Height]; b.GetPixels(argb, 0, b.Width, 0, 0, b.Width, b.Height); encodeYUV420SP(yuv, argb, b.Width, b.Height); var yuvimage = new YuvImage(yuv, _CameraColorFormat, _Width, _Height, null); var yuvarray = yuvimage.GetYuvData(); colorcorrection(ref yuvarray, b.Width, b.Height); //method for fixing common color matching issues see below for comments inputBuf.Put(yuvarray); chunkSize = yuvarray.Length; //yuv = null; //GC.Collect(); //essential to fix memory leak from new YuvImage allocation above b.Recycle(); } // the buffer should be sized to hold one full frame inputBuf.Clear(); _Encoder.QueueInputBuffer(inputBufIndex, 0, chunkSize, ptsUsec, 0); frameIndex++; } } else { // either all in use, or we timed out during initial setup Log.Warn(TAG, "input buffer not available"); } } ByteBuffer[] encoderOutputBuffers = _Encoder.GetOutputBuffers(); var mBufferInfo = new MediaCodec.BufferInfo(); int encoderStatus = _Encoder.DequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC); if (encoderStatus == (int)MediaCodecInfoState.TryAgainLater) { Log.Info(TAG, "no output available, spinning to await EOS"); } else if (encoderStatus == (int)MediaCodecInfoState.OutputBuffersChanged) { // not expected for an encoder Log.Warn(TAG, "not expected OutputBuffersChanged happened"); encoderOutputBuffers = _Encoder.GetOutputBuffers(); } else if (encoderStatus == (int)MediaCodecInfoState.OutputFormatChanged) { // should happen before receiving buffers, and should only happen once if (_MuxerStarted) { Log.Error(TAG, "format changed twice and should never happen"); throw new RuntimeException("format changed twice"); } MediaFormat newFormat = _Encoder.OutputFormat; Log.Info(TAG, "format changed and starting MUX"); _TrackIndex = _Muxer.AddTrack(newFormat); _Muxer.Start(); _MuxerStarted = true; } else if (encoderStatus < 0) { Log.Warn(TAG, "unexpected but lets ignore"); // let's ignore it } else { ByteBuffer encodedData = encoderOutputBuffers[encoderStatus]; if (encodedData == null) { Log.Error(TAG, string.Format("encoderOutputBuffer {0} was null!!", encoderStatus)); throw new RuntimeException(string.Format("encoderOutputBuffer {0} was null!!", encoderStatus)); } if ((mBufferInfo.Flags & MediaCodecBufferFlags.CodecConfig) != 0) { // The codec config data was pulled out and fed to the muxer when we got // the INFO_OUTPUT_FORMAT_CHANGED status. Ignore it. mBufferInfo.Size = 0; } if (mBufferInfo.Size != 0) { if (!_MuxerStarted) { Log.Error(TAG, "muxer hasnt started!!"); throw new RuntimeException("muxer hasnt started"); } // adjust the ByteBuffer values to match BufferInfo (not needed?) old //encodedData.Position(mBufferInfo.Offset); //encodedData.Limit(mBufferInfo.Offset + this.mBufferInfo.Size); _Muxer.WriteSampleData(_TrackIndex, encodedData, mBufferInfo); Log.Info(TAG, string.Format("{0} bytes to muxer", mBufferInfo.Size)); } _Encoder.ReleaseOutputBuffer(encoderStatus, false); if ((mBufferInfo.Flags & MediaCodecBufferFlags.EndOfStream) != 0) { Log.Info(TAG, "End of Stream Reached!!"); break; } } } } catch (Exception e) { Log.Error(TAG, "Decode or Muxer failed", e, e.Message); throw; } }
public void OnPreviewFrame(byte [] bytes, Android.Hardware.Camera camera) { if ((DateTime.Now - lastPreviewAnalysis).TotalMilliseconds < options.DelayBetweenAnalyzingFrames) { return; } try { /* OLD Android Code * //Fix for image not rotating on devices * byte[] rotatedData = new byte[bytes.Length]; * for (int y = 0; y < height; y++) { * for (int x = 0; x < width; x++) * rotatedData[x * height + height - y - 1] = bytes[x + y * width]; * } * * var cameraParameters = camera.GetParameters(); * * //Changed to using a YUV Image to get the byte data instead of manually working with it! * var img = new YuvImage(rotatedData, ImageFormatType.Nv21, cameraParameters.PreviewSize.Width, cameraParameters.PreviewSize.Height, null); * var dataRect = GetFramingRectInPreview(); * * var luminance = new PlanarYUVLuminanceSource (img.GetYuvData(), width, height, dataRect.Left, dataRect.Top, dataRect.Width(), dataRect.Height(), false); * //var luminance = new PlanarYUVLuminanceSource(img.GetYuvData(), cameraParameters.PreviewSize.Width, cameraParameters.PreviewSize.Height, 0, 0, cameraParameters.PreviewSize.Width, cameraParameters.PreviewSize.Height, false); * var binarized = new BinaryBitmap (new ZXing.Common.HybridBinarizer(luminance)); * var result = reader.decodeWithState(binarized); */ var cameraParameters = camera.GetParameters(); var img = new YuvImage(bytes, ImageFormatType.Nv21, cameraParameters.PreviewSize.Width, cameraParameters.PreviewSize.Height, null); var dataRect = GetFramingRectInPreview(); //var barcodeReader = new BarcodeReader(null, p => new PlanarYUVLuminanceSource(img.GetYuvData(), img.Width, img.Height, dataRect.Left, dataRect.Top, // dataRect.Width(), dataRect.Height(), false), null, null) //{ // AutoRotate = true, // TryHarder = true, //}; var barcodeReader = new BarcodeReader(null, null, null, (p, w, h, f) => new PlanarYUVLuminanceSource(p, w, h, 0, 0, w, h, false)) //new PlanarYUVLuminanceSource(p, w, h, dataRect.Left, dataRect.Top, dataRect.Width(), dataRect.Height(), false)) { AutoRotate = true, TryHarder = false }; if (this.options.PureBarcode.HasValue && this.options.PureBarcode.Value) { barcodeReader.PureBarcode = this.options.PureBarcode.Value; } if (this.options.PossibleFormats != null && this.options.PossibleFormats.Count > 0) { barcodeReader.PossibleFormats = this.options.PossibleFormats; } var result = barcodeReader.Decode(img.GetYuvData(), img.Width, img.Height, RGBLuminanceSource.BitmapFormat.Unknown); lastPreviewAnalysis = DateTime.Now; if (result == null || string.IsNullOrEmpty(result.Text)) { return; } Android.Util.Log.Debug("ZXing.Mobile", "Barcode Found: " + result.Text); ShutdownCamera(); activity.OnScan(result); } catch (ReaderException) { Android.Util.Log.Debug("ZXing.Mobile", "No barcode Found"); // ignore this exception; it happens every time there is a failed scan } catch (Exception) { // TODO: this one is unexpected.. log or otherwise handle it throw; } }