2015-07-14 5 views
5

Я пытаюсь заставить новую камеру2 работать с простым SurfaceView, и у меня возникают некоторые проблемы с предварительным просмотром в реальном времени. На некоторых устройствах изображение растягивается из пропорций, хорошо смотря на других.Camera2 с SurfaceView

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

На Nexus 5 это выглядит отлично, но один из устройств Samsung уходит. Кроме того, устройства Samsung имеют черную рамку в правой части предварительного просмотра.

Действительно ли невозможно работать с SurfaceView или это время для перехода на TextureView?

+0

Похоже, что предварительный просмотр не такой размер, как вы думаете. Вы можете найти аналогичный вопрос, с некоторыми советами по использованию 'dumpsys' для изучения проблемы, в этом сообщении: http://stackoverflow.com/questions/30714469/android-supported-camera-preview-size-is-wrong- пропорции – fadden

+0

вы нашли способ использовать SurfaceView с Camera2 и без искаженного предварительного просмотра? – vkislicins

+0

Я переехал в TextureView - это намного более гибко. – slott

ответ

0

Я никогда не работал с Camera2 (но очень интересен в новой технологии), и все, что я могу предложить, это следовать образцам. И если вы тщательно проверить, образец использует пользовательский TextureView, вы должны probalby попытаться скопировать его в проект:

http://developer.android.com/samples/Camera2Basic/src/com.example.android.camera2basic/AutoFitTextureView.html

/** 
* A {@link TextureView} that can be adjusted to a specified aspect ratio. 
*/ 
public class AutoFitTextureView extends TextureView { 

также учитывая, что различались между SurfaceView и TextureView (теоретически) только что вы можете использовать как обычный вид в макете, а другой «пробивает целое» через иерархию представлений и что Camera2 доступен только в API21 + ... не должно быть вреда при переходе на TextureView

+0

Я начал там и перевел это на поверхность - и вот тогда дерьмо стало ударять по вентилю :( – slott

+0

ну, учитывая, что TextureView - это API 14, а Camera2 - API 21, на самом деле нет причин. Просто верните его, нет? – Budius

+0

Работа на кросс-платформе lib - так минимум 11, так что было бы неплохо заставить это работать ... Но если не мин будет 14 ... – slott

1

Да, это обязательно возможно. Обратите внимание, что SurfaceView и связанные с ним Surface - это две разные вещи, и каждому может/должен быть присвоен размер.

Surface - это фактический буфер памяти, который будет удерживать выходной сигнал камеры, и, таким образом, его размер определяет размер фактического изображения, которое вы получите от каждого кадра. Для каждого формата, доступного с камеры, существует небольшой набор возможных (точных) размеров, которые вы можете создать в этом буфере.

SurfaceView - это то, что отображает это изображение, когда оно доступно, и может в основном быть любого размера в вашем макете. Он будет растягивать связанные с ним данные изображения в соответствии с его размером макета, но обратите внимание, что размер этого экрана отличается от размера данных. Android автоматически изменит размер данных изображения для отображения. Это то, что, вероятно, вызывает ваше растяжение.

Например, вы можете сделать SurfaceView основанной кнопкуШирину View, похожий на AutoFitTextureView в camera2basic, как показано ниже (это то, что я использую):

import android.content.Context; 
import android.util.AttributeSet; 
import android.view.SurfaceView; 

public class AutoFitSurfaceView extends SurfaceView { 

    private int mRatioWidth = 0; 
    private int mRatioHeight = 0; 

    public AutoFitSurfaceView(Context context) { 
     this(context, null); 
    } 

    public AutoFitSurfaceView(Context context, AttributeSet attrs) { 
     this(context, attrs, 0); 
    } 

    public AutoFitSurfaceView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    /** 
    * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio 
    * calculated from the parameters. Note that the actual sizes of parameters don't matter, that 
    * is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result. 
    * 
    * @param width Relative horizontal size 
    * @param height Relative vertical size 
    */ 
    public void setAspectRatio(int width, int height) { 
     if (width < 0 || height < 0) { 
      throw new IllegalArgumentException("Size cannot be negative."); 
     } 
     mRatioWidth = width; 
     mRatioHeight = height; 
     requestLayout(); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
     int width = MeasureSpec.getSize(widthMeasureSpec); 
     int height = MeasureSpec.getSize(heightMeasureSpec); 
     if (0 == mRatioWidth || 0 == mRatioHeight) { 
      setMeasuredDimension(width, height); 
     } else { 
      if (width < height * mRatioWidth/mRatioHeight) { 
       setMeasuredDimension(width, width * mRatioHeight/mRatioWidth); 
      } else { 
       setMeasuredDimension(height * mRatioWidth/mRatioHeight, height); 
      } 
     } 
    } 
} 
+2

Это _exactly_ то, что у меня есть - на основе кода camera2basic от Google. Проблема в том, что фактическое изображение, отображаемое на поверхности, искажается на некоторых устройствах, таких как Samsung S4 и Nexus 4, но отлично смотрится на Nexus 5. Я пробовал много вещей - даже размер жестко закодированных поверхностей соответствовал размерным форматам предварительного просмотра - все же в конечном итоге с искаженным представлением. С TextureView его все прекрасное и денди - за исключением моей гордости :( – slott

+0

Каково соотношение сторон изображений, которые вы настраиваете на поверхности для устройств с неправильным управлением? Я только угадываю, не видя искаженные изображения, о которых вы говорите, но является результатом возврата samsung samsung 16x9 в буфер изображения 4x3 с большим количеством неиспользуемой черной полосы? Возможно, вам стоит попробовать установить Surface для одного из 16x9 выходных размеров и SurfaceView таким же образом и посмотреть, что происходит? – rcsumner

+0

Я использовал 1280 x 720, а также размер предварительного просмотра камеры – slott

1

в документации для createCaptureSession он говорит

Для рисования SurfaceView: после создания поверхности SurfaceView задайте размер поверхности с помощью setFixedSize (int, int) равным . Один из размеров, возвращаемый getOutputSizes (SurfaceHolder.class)

+0

№ Это не сработает. Требуется сделать «пользовательский» размер. Представление, которое не должно быть ограничено иерархией, что экземпляр представления завышен и встроен. Сообщение rcsumner похоже на путь. Я пытаюсь это сделать сейчас. Дам вам знать. – BoiseBaked

+2

Я пробовал пост @rcsumner, и это не сработало для меня. Я не понимаю, почему так сложно избежать растяжения изображения (искажение пропорций) при работе с API-интерфейсом камеры2 и видео. Поверхность, которая будет отображать изображение, всегда создается сначала. Почему изображение «просто» не может быть масштабировано на поверхности с использованием черных границ, если это необходимо, без искажений? Должен быть прямой способ сделать это. – BoiseBaked