Подтвердить что ты не робот

Предварительный просмотр камеры Android с использованием кода Grafika CameraCapture

Я ищу помощь с проблемой, с которой я столкнулся, используя код Grafika CameraCaptureActivity. Я хочу создать приложение, которое может записывать камеру и отображать предварительный просмотр, поэтому этот пример и код выглядели точно так, как я хотел, и до сих пор это было замечательно, этот выпуск.

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

Вот как это выглядит:

Предварительный просмотр растянут

Как вы можете видеть, он растягивается горизонтально, так как лист заметки является идеальным квадратом.

Для этого примера на Samsung Galaxy S4 размер предварительного просмотра камеры составляет 1280x720 (извлечен из доступных размеров предварительного просмотра с использованием API Camera2), а GLSurfaceView - 1920x1080 для покрытия всего экрана.

Когда он появляется?

Проблема возникает, когда SurfaceView масштабируется по сравнению с выходом камеры, даже если я всегда убеждаюсь, что соотношение остается правильным (1920x1080= 1,5 * 1280x720).

Какой код вы используете?

Я использую код Grafika, включая:

Некоторые журналы?

Вот что выглядит свалка SurfaceFlinger:

Hardware Composer state (version 01030000):
  mDebugForceFakeVSync=0
  Display[0] configurations (* current):
    * 0: 1080x1920, xdpi=442.450989, ydpi=439.351013, secure=1 refresh=16666667
  numHwLayers=3, flags=00000000
    type   |  handle  | hint | flag | tr | blnd |  format     |     source crop(l,t,r,b)       |           frame        |      dirtyRect         |  name 
------------+----------+----------+----------+----+-------+----------+-----------------------------------+---------------------------+-------------------
       HWC | b3b12ba0 | 0002 | 0000 | 00 | 0100 | RGB_888     |    0.0,    0.0, 1080.0, 1920.0 |    0,    0, 1080, 1920 | [    0,    0, 1080, 1920] | SurfaceView
       HWC | b3d12740 | 0002 | 0000 | 00 | 0105 | RGBA_8888   |    0.0,    0.0, 1065.0, 1905.0 |    0,    0, 1065, 1905 | [    0,    0, 1065, 1905] | com.mybundle.myapp/com.mybundle.myapp.activity.MyActivity
 FB TARGET | b6a55c40 | 0000 | 0000 | 00 | 0105 | RGBA_8888   |    0.0,    0.0, 1080.0, 1920.0 |    0,    0, 1080, 1920 | [    0,    0,    0,    0] | HWC_FRAMEBUFFER_TARGET

Layer 0xb4094000 (SurfaceView)
  Region transparentRegion (this=0xb4094160, count=1)
    [  0,   0,   0,   0]
  Region visibleRegion (this=0xb4094008, count=1)
    [  0,   0, 1920, 1080]
      layerStack=   0, z=    21015, pos=(0,0), size=(1920,1080), crop=(   0,   0,1920,1080), isOpaque=1, invalidate=0, alpha=0xff, flags=0x00000002, tr=[1.00, 0.00][0.00, 1.00]
      client=0xb66190c0
      format= 4, activeBuffer=[1080x1920:1536,  3], queued-frames=0, mRefreshPending=0
            mTexName=116 mCurrentTexture=0
            mCurrentCrop=[0,0,0,0] mCurrentTransform=0x7
            mAbandoned=0
            -BufferQueue mMaxAcquiredBufferCount=1, mDequeueBufferCannotBlock=0, default-size=[1920x1080], default-format=4, transform-hint=04, FIFO(0)={}
            >[00:0xb1c18500] state=ACQUIRED, 0xb3b12ba0 [1080x1920:1536,  3]

Код размера предварительного просмотра камеры?

StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

// Retrieve display size
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point displaySize = new Point();
display.getSize(displaySize);

// Choose the sizes for camera preview
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
                    displaySize.x, displaySize.y, captureWidth, captureHeight);

private static Size chooseOptimalSize(Size[] choices, int screenWidth, int screenHeight, int captureWidth, int captureHeight)
    {
        // Collect the supported resolutions that are at least as big as the screen && wanted capture size
        List<Size> bigEnough = new ArrayList<>();
        // Collect the supported resolutions that are at least as big as the wanted capture size but < to screensize
        List<Size> smallerButEnough = new ArrayList<>();

        for (Size option : choices) {
            if (option.getHeight() == option.getWidth() * captureHeight / captureWidth) {
                if( option.getWidth() >= screenWidth && option.getHeight() >= screenHeight )
                {
                    bigEnough.add(option);
                }
                else
                {
                    smallerButEnough.add(option);
                }
            }
        }

        // Pick the smallest of those, assuming we found any
        if (bigEnough.size() > 0)
        {
            return Collections.min(bigEnough, new CompareSizesByArea());
        }
        // Pick the biggest of those, assuming we found any
        else if( smallerButEnough.size() > 0 )
        {
            return Collections.max(smallerButEnough, new CompareSizesByArea());
        }
        else
        {
            Log.e(TAG, "Couldn't find any suitable preview size");
            return choices[0];
        }
    }

Что вы пробовали?

Сначала я подумал, что это проблема Camera2, поэтому я попытался использовать только старый API-интерфейс Camera, но результат тот же.

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

Моя ставка заключается в том, что при изменении размера поверхности применяется преобразование OpenGL, но я являюсь чистым noob в OpenGL, поэтому я не смог найти что-либо, что работает. Я пытаюсь добавить эти строки, но это не помогает:

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
    Log.d(TAG, "onSurfaceChanged " + width + "x" + height);

    gl.glViewport(0, 0, width, height);
    gl.glClear(GLES10.GL_COLOR_BUFFER_BIT | GLES10.GL_DEPTH_BUFFER_BIT);
}

Другой пример, прямо из Grafika:

Вот еще один пример проблемы, прямо из приложения Grafika.

Телефон: Galaxy S3 Neo (GT-I9301L) - Android 4.4.2

В телефоне есть экран 1280x720, камера открывается с разрешением 640x480, отображаемым в 573x430. Вот как это выглядит:

Растяжка на GS3 Neo

Журналы SurfaceFlinger:

Hardware Composer state (version  1030000):
  mDebugForceFakeVSync=0
  Display[0] : 720x1280, xdpi=304.799011, ydpi=306.716003, refresh=16666667
  numHwLayers=4, flags=00000000
    type    |  handle  |   hints  |   flags  | tr | blend |  format  |          source crop            |           frame           name 
------------+----------+----------+----------+----+-------+----------+---------------------------------+--------------------------------
        HWC | b84a3d18 | 00000002 | 00000000 | 00 | 00100 | 00000002 | [    0.0,    0.0,  430.0,  573.0] | [   32,  353,  462,  926] SurfaceView
        HWC | b841b080 | 00000002 | 00000000 | 00 | 00105 | 00000001 | [    0.0,    0.0,  670.0, 1280.0] | [    0,    0,  670, 1280] com.android.grafika/com.android.grafika.CameraCaptureActivity
        HWC | b8423250 | 00000002 | 00000000 | 00 | 00105 | 00000001 | [    0.0,    0.0,   50.0, 1280.0] | [  670,    0,  720, 1280] StatusBar
  FB TARGET | b8412d50 | 00000000 | 00000000 | 00 | 00105 | 00000001 | [    0.0,    0.0,  720.0, 1280.0] | [    0,    0,  720, 1280] HWC_FRAMEBUFFER_TARGET


+ Layer 0xb8416080 (SurfaceView) id=112
  Region transparentRegion (this=0xb84169d0, count=1)
    [  0,   0,   0,   0]
  Region visibleRegion (this=0xb8416088, count=1)
    [353, 258, 926, 688]
      layerStack=   0, z=    21015, pos=(353,258), size=( 573, 430), crop=(   0,   0, 573, 430), isOpaque=1, invalidate=0, alpha=0xff, flags=0x00000000, tr=[1.00, 0.00][0.00, 1.00]
      client=0xb841d7c8
      format= 4, activeBuffer=[ 430x 573: 448,  2], queued-frames=0, mRefreshPending=0
            mTexName=95 mCurrentTexture=1
            mCurrentCrop=[0,0,0,0] mCurrentTransform=0x7
            mAbandoned=0
            -BufferQueue mMaxAcquiredBufferCount=1, mDequeueBufferCannotBlock=0, default-size=[573x430], default-format=4, transform-hint=04, FIFO(0)={}
             [00:0xb84439a8] state=FREE    , 0xb849a528 [ 430x 573: 448,  2]
            >[01:0xb8421128] state=ACQUIRED, 0xb84a3d18 [ 430x 573: 448,  2]
             [02:0xb84238e8] state=FREE    , 0xb84432f8 [ 430x 573: 448,  2]

Журнал приложений Grafika:

04-18 18:06:49.954 14383-14383/com.android.grafika D/Grafika: onCreate complete: [email protected]
04-18 18:06:49.954 14383-14383/com.android.grafika D/Grafika: onResume -- acquiring camera
04-18 18:06:50.064 14383-14383/com.android.grafika D/Grafika: Camera preferred preview size for video is 1920x1080
04-18 18:06:50.064 14383-14383/com.android.grafika D/Grafika-AFL: Setting aspect ratio to 1.3333333333333333 (was -1.0)
04-18 18:06:50.064 14383-14383/com.android.grafika D/Grafika: onResume complete: [email protected]
04-18 18:06:50.064 14383-32312/com.android.grafika D/Grafika: setCameraPreviewSize
04-18 18:06:50.094 14383-14383/com.android.grafika D/Grafika-AFL: onMeasure target=1.3333333333333333 width=[MeasureSpec: EXACTLY 1216] height=[MeasureSpec: EXACTLY 526]
04-18 18:06:50.094 14383-14383/com.android.grafika D/Grafika-AFL: new size=701x526 + padding 0x0
04-18 18:06:50.094 14383-14383/com.android.grafika D/Grafika-AFL: onMeasure target=1.3333333333333333 width=[MeasureSpec: EXACTLY 1216] height=[MeasureSpec: EXACTLY 430]
04-18 18:06:50.094 14383-14383/com.android.grafika D/Grafika-AFL: new size=573x430 + padding 0x0
04-18 18:06:50.124 14383-32312/com.android.grafika D/Grafika: onSurfaceCreated
04-18 18:06:50.134 14383-32312/com.android.grafika D/Grafika: Created program 3 (TEXTURE_EXT)
04-18 18:06:50.144 14383-32312/com.android.grafika D/Grafika: onSurfaceChanged 573x430
04-18 18:06:50.144 14383-32312/com.android.grafika D/Grafika: Updating filter to 0
04-18 18:06:50.154 14383-14383/com.android.grafika D/Grafika: onItemSelected: 0
04-18 18:06:50.154 14383-14383/com.android.grafika D/Grafika: CameraHandler [Handler (com.android.grafika.CameraCaptureActivity$CameraHandler) {42aeec70}]: what=0
04-18 18:06:50.514 14383-14383/com.android.grafika D/Grafika-AFL: onMeasure target=1.3333333333333333 width=[MeasureSpec: EXACTLY 1216] height=[MeasureSpec: EXACTLY 526]
04-18 18:06:50.514 14383-14383/com.android.grafika D/Grafika-AFL: new size=701x526 + padding 0x0
04-18 18:06:50.514 14383-14383/com.android.grafika D/Grafika-AFL: onMeasure target=1.3333333333333333 width=[MeasureSpec: EXACTLY 1216] height=[MeasureSpec: EXACTLY 430]
04-18 18:06:50.514 14383-14383/com.android.grafika D/Grafika-AFL: new size=573x430 + padding 0x0
04-18 18:06:50.544 14383-14383/com.android.grafika D/AbsListView: onVisibilityChanged() is called, visibility : 4
04-18 18:06:50.544 14383-14383/com.android.grafika D/AbsListView: unregisterIRListener() is called 

Так...

Если один из вас, ребята, имеет представление о том, как заставить его работать, я хотел бы услышать от него.

Спасибо!

4b9b3361

Ответ 1

Мне жаль моего последнего ответа, это было глупо и не разрешило проблему. Но я основал другое решение и протестировал его на 5 устройствах, используя различные пропорции камеры. Как я понял, вы используете код Grafika. Попробуйте удалить parms.setRecordingHint(true); Так что теперь я использую только param.setPictureSize() param.setPreviewSize() с тем же соотношением сторон в параметрах камеры. Также я установил размер gl view с этим аспектом, я сделал его сам. В grafika он использовал фиксированный размер, afaik. Надеюсь, это поможет вам.