Как заставить камеру camera2 api работать во второй раз? - PullRequest
0 голосов
/ 17 марта 2019

Я использую Xamarin / Android (не Forms), пытаясь интегрировать пример API camera2basic в мой проект. https://developer.xamarin.com/samples/monodroid/android5.0/Camera2Basic/

Я ничего не изменил в образце, и меня интересует только использование основной камеры и только создание снимка.

Мой проект имеет MainActivity, а camera2 - это один из фрагментов, который я называю так:

 string fragmentTag = this.Resources.GetString(Resource.String.camera_form);

 // Begin the transaction
 FragmentTransaction trans = this.FragmentManager.BeginTransaction();

 // Replace the old fragment with the new one.
 trans.Add(Resource.Id.fragment_container, camera2BasicFragment, fragmentTag);

 // Add the transaction to the back stack.
 // The tag is added so we can use PopBackStack to skip a screen on the back key
 trans.AddToBackStack(fragmentTag);

 // Don't forget to commit
 trans.Commit();

Все работает с первого раза. Он берет фотографию и сохраняет ее в папке.

Во второй раз, когда я запускаю его, он показывает предварительный просмотр, затем, когда я фотографирую, он падает здесь, где бросок:

  public void CaptureStillPicture()
  {
     try
     {
        var activity = Activity;
        if (null == activity || null == mCameraDevice)
        {
           return;
        }
        // This is the CaptureRequest.Builder that we use to take a picture.
        if (stillCaptureBuilder == null)
           stillCaptureBuilder = mCameraDevice.CreateCaptureRequest(CameraTemplate.StillCapture);

        stillCaptureBuilder.AddTarget(mImageReader.Surface);

        // Use the same AE and AF modes as the preview.
        stillCaptureBuilder.Set(CaptureRequest.ControlAfMode, (int)ControlAFMode.ContinuousPicture);
        SetAutoFlash(stillCaptureBuilder);

        // Orientation
        int rotation = (int)activity.WindowManager.DefaultDisplay.Rotation;
        stillCaptureBuilder.Set(CaptureRequest.JpegOrientation, GetOrientation(rotation));

        mCaptureSession.StopRepeating();

        try
        {
           mCaptureSession.Capture(stillCaptureBuilder.Build(), new CameraCaptureStillPictureSessionCallback(this), null);
        }
        catch (System.Exception e)
        {
           throw;
        }

     }
     catch (CameraAccessException e)
     {
        e.PrintStackTrace();
     }
  }

С этой ошибкой:

{Java.Lang.IllegalArgumentException: CaptureRequest contains unconfigured Input/Output Surface!
  at Java.Interop.JniEnvironment+InstanceMethods.CallIntMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00069] in <286213b9e14c442ba8d8d94cc9dbec8e>:0 
  at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeAbstractInt32Method (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00014] in <286213b9e14c442ba8d8d94cc9dbec8e>:0 
  at Android.Hardware.Camera2.CameraCaptureSessionInvoker.Capture (Android.Hardware.Camera2.CaptureRequest request, Android.Hardware.Camera2.CameraCaptureSession+CaptureCallback listener, Android.OS.Handler handler) [0x00078] in <b781ed64f1d743e7881ac038e0fbdf85>:0 
  at RvsMobileApp.Activities.Camera2BasicFragment.CaptureStillPicture () [0x000b7] in C:\Source\RVS\rvs-mobile-app\src\Rvs.Mobile.App\Activities\Camera2BasicFragment.cs:807 
  --- End of managed Java.Lang.IllegalArgumentException stack trace ---
java.lang.IllegalArgumentException: CaptureRequest contains unconfigured Input/Output Surface!
    at android.hardware.camera2.CaptureRequest.convertSurfaceToStreamId(CaptureRequest.java:674)
    at android.hardware.camera2.impl.CameraDeviceImpl.submitCaptureRequest(CameraDeviceImpl.java:1066)
    at android.hardware.camera2.impl.CameraDeviceImpl.capture(CameraDeviceImpl.java:936)
    at android.hardware.camera2.impl.CameraCaptureSessionImpl.capture(CameraCaptureSessionImpl.java:173)
    at md5bbb797339b35f7667da89d6634e22c37.CameraCaptureListener.n_onCaptureCompleted(Native Method)
    at md5bbb797339b35f7667da89d6634e22c37.CameraCaptureListener.onCaptureCompleted(CameraCaptureListener.java:37)
    at android.hardware.camera2.impl.CameraCaptureSessionImpl$1.lambda$onCaptureCompleted$3(CameraCaptureSessionImpl.java:640)
    at android.hardware.camera2.impl.-$$Lambda$CameraCaptureSessionImpl$1$OA1Yz_YgzMO8qcV8esRjyt7ykp4.run(Unknown Source:8)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:214)
    at android.os.HandlerThread.run(HandlerThread.java:65)
}
    base: {Java.Lang.RuntimeException}
    JniPeerMembers: {Android.Runtime.XAPeerMembers}

Сначала я подумал, что это утечка памяти, поэтому я убедился, что мой фрагмент убивает себя. Вот как я заканчиваю фрагмент, когда нажата готовая кнопка:

    case Resource.Id.camera_finished:
       // EventHandler<DialogClickEventArgs> nullHandler = null;
       Activity activity = Activity;
       if (activity != null)
       {
          // Send all of the data to the service
          // SendPhotosAndDataToService();

          // Call the paren activitity's back to END this Fragment
          activity.FragmentManager.BeginTransaction().Remove(this).CommitNow();
          //activity.OnBackPressed();

       }
       break;

Вот мои шаги для воспроизведения ошибки:

Запустите камеру (загрузите фрагмент) Посмотреть превью Сфотографировать Вернуться к основной деятельности (закрыть фрагмент)

Запустите камеру (загрузите фрагмент) Посмотреть превью Сфотографируй CRASH !!!

Пока я не делаю никаких фотографий, я могу загружать и выгружать фрагмент столько раз, сколько мне нужно.

Я гуглил «CaptureRequest содержит ненастроенную поверхность ввода / вывода!», И не получил достаточно информации, чтобы действительно понять проблему. Я думаю, что что-то не очищается после первого запуска. Я работаю над этим вопросом уже несколько дней.

Ответы [ 2 ]

1 голос
/ 17 марта 2019

Имена stillCaptureBuilder повторно инициализированы при восстановлении фрагмента камеры. Более того, убедитесь, что вы очищаете stillCaptureBuilder , когда фрагмент уничтожен.

0 голосов
/ 17 марта 2019

Как указал Алекс Кон, и когда я прочитал эту статью, я обнаружил: https://hofmadresu.com/2018/09/11/android-camera2-trials-and-tribulations.html

Кстати, отличный ресурс, пример кода не выпускал stillCaptureBuilder, поэтому его можно использовать во второй раз.

      public void CaptureStillPicture()
      {
         try
         {
            var activity = Activity;
            if (null == activity || null == mCameraDevice)
            {
               return;
            }

            // THIS WAS NOT RELEASING THE RESOURCES AND SHOULD BE REMOVED FROM THE SAMPLE!
            //// This is the CaptureRequest.Builder that we use to take a picture.
            ////if (stillCaptureBuilder == null)
            ////   stillCaptureBuilder = mCameraDevice.CreateCaptureRequest(CameraTemplate.StillCapture);

// This is the proper code            
var stillCaptureBuilder = mCameraDevice.CreateCaptureRequest(CameraTemplate.StillCapture);

            stillCaptureBuilder.AddTarget(mImageReader.Surface);

            // Use the same AE and AF modes as the preview.
            stillCaptureBuilder.Set(CaptureRequest.ControlAfMode, (int)ControlAFMode.ContinuousPicture);
            SetAutoFlash(stillCaptureBuilder);

            // Orientation
            int rotation = (int)activity.WindowManager.DefaultDisplay.Rotation;
            stillCaptureBuilder.Set(CaptureRequest.JpegOrientation, GetOrientation(rotation));

            mCaptureSession.StopRepeating();
            mCaptureSession.AbortCaptures();

            try
            {
               mCaptureSession.Capture(stillCaptureBuilder.Build(), new CameraCaptureStillPictureSessionCallback(this), null);
            }
            catch (System.Exception e)
            {
               throw;
            }

         }
         catch (CameraAccessException e)
         {
            e.PrintStackTrace();
         }
      }

Я документирую это, чтобы любой, кто борется с камерой2, мог учиться. Спасибо как всегда

...