2016-10-13 3 views
2

Я пытаюсь настроить предварительный просмотр камеры с помощью ImageReader (формат YUV_420_888) с использованием Camera2 API. Прежде всего я должен выбрать поддерживаемый размер предварительного просмотра:Android Camera2 Предварительный просмотр размеры вывода

StreamConfigurationMap scmap = camCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 
Size previewSizes[] = scmap.getOutputSizes(ImageReader.class); 

My Nexus 5X поддерживает следующие размеры:

[4032x3024,4000x3000,3840x2160,3288x2480,3200x2400,2592x1944,2688x1512,2048x1536,1920x1080,1600x1200,1440x1080,1280x960,1280x768,1280x720,1024x768,800x600,864x480,800x480,720x480,640x480,640x360,352x288,320x240,176x144,160x120] 

Подготовьте экземпляр ImageReader и начать CaptureSession с повторением запроса захвата:

mImageReader = ImageReader.newInstance(W,H, ImageFormat.YUV_420_888,1); 

Затем я пытаюсь прочитать каждый кадр предварительного просмотра (для дальнейшей обработки и отображения через GLES) в OnImageAvailableListener. И то, что я хочу знать - сколько байт Y-канал я получил:

public void onImageAvailable(ImageReader reader) { 
     ByteBuffer yBuffer = mImageReader.acquireNextImage().getPlanes()[0].getBuffer(); 
     Log.d("Camera2Debug","Y-channel bytes received: " + yBuffer.remaining()); 
     ... 
    } 

Y-канал для YUV_420_888 изображения должны содержать WxH байт, где W - это ширина и H - это высота рассматриваемого изображения.

Проблема: Для некоторых поддерживается просмотр размеров фактического размера yBuffer не соответствует ожидаемому значению (WxH).

Например:

Preview Size | Y-bytes received | Y-bytes expected | match 
4032x3024  | 12 192 768  | 12 192 768  | yes 
1920x1080  | 2 073 600  | 2 073 600  | yes 
1440x1080  | 1 589 728  | 1 555 200  | no 
1280x960  | 1 228 800  | 1 228 800  | yes 
1280x768  | 983 040  | 983 040  | yes 
800x600  | 499 168  | 480 000  | no 
... 
499168 

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

Что я делаю неправильно?

+0

Вы можете отлаживать дальнейшую длину и длину журнала для возвращаемого изображения, но я думаю, что вы, вероятно, захотите использовать 'scmap.getOutputSizes (ImageFormat.YUV_420_888)' при первоначальном получении размеров. В документации 'getOutputSizes (класс )' возвращает размеры для формата 'PRIVATE'. См. Здесь: https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputSizes(java.lang.Class ) – msandiford

+0

Спасибо за ваш комментарий. Я забыл упомянуть, что размер изображения, возвращаемого 'приобретатьNextImage()', является правильным (равным размеру предварительного просмотра). Проблема заключается в размере 'getPlanes() [0] .getBuffer()'. – frumle

+0

Решено: [ссылка] (http://stackoverflow.com/questions/30405977/nexus-9-camera2-api-yuv-420-888-vs-getoutputsizes). – frumle

ответ

2

Возможно, вы не учтите https://developer.android.com/reference/android/media/Image.Plane.html#getRowStride(), который может быть больше ширины (но по крайней мере равен ему). Фактический размер буфера будет

size = rowStride * height - (rowStride - width) 

с вычитанием (rowStride - ширина), поскольку последняя строка не включает в себя прокладку мимо последнего пикселя.

+0

Вы правы, мне все равно, как данные хранятся внутри массива (например, я использовал его с помощью PreviewCallback со старой камеры api). Итак, теперь мне нужно извлечь «полезные» данные из массивов вручную? – frumle

+1

Да, если вам нужно использовать данные. Аппаратное обеспечение камеры обычно использует шаг, потому что размер каждой строки часто должен быть кратным 16 пикселям/байтам из-за требований к сопоставлению памяти. У старого API не было шага, что часто приводило к дополнительной копии для удаления шага в кишках устройства.Это дополнительные накладные расходы, которые вы можете избежать, ценой немного больше работы с вашей стороны. –