Motorola Atrix Несогласованный предварительный просмотр - PullRequest
0 голосов
/ 15 июля 2011

Я разрабатываю приложение, которое отправляет поток изображений JPEG (поток MJPEG) на удаленный ПК.У меня проблемы с изменением частоты кадров предварительного просмотра в параметрах камеры.Кажется, что независимо от того, какую скорость я установил, камера выдает только кадр со скоростью 15 кадров в секунду.Сначала я подумал, что это связано со сжатием изображения, а затем с передачей данных.Но я создал отладочный экземпляр, где я сохраняю первое сжатое изображение JPEG и отправляю это изображение каждый раз, когда вызывается функция onPreviewFrame.Это приводит к надежным 15 к / с, но я установил его на 30 к / с.У кого-нибудь есть идеи, почему fps так непоследователен?Когда я настраиваю его на сжатие каждого кадра предварительного просмотра и отправку по Wi-Fi, я получаю скорость 5-40 кадров в секунду, и он скачет повсюду.

Вот мой код для моего предварительного просмотра (настраивает камеруна полном экране)

public class Preview extends SurfaceView implements PreviewCallback, SurfaceHolder.Callback {
SurfaceHolder mHolder;
Camera mCamera;
DatagramSocket udpSocket = null;
final int PORT = 1235;
final String IPAddress = "192.168.1.101";
int packetSize = 1024; // Specify max size of each UDP packet
int WIDTH = 640;
int HEIGHT = 480;   
int FPS = 30;       
int quality = 70;
/**
 * Initialize the Camera Preview Holder and create a udpSocket.
 * @param context
 */
Preview(Context context) {
    super(context);
    mHolder = getHolder();
    mHolder.addCallback(this);
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    try {
        udpSocket = new DatagramSocket();
    } catch (SocketException e) {
        Log.e(tag, "Error creating UDP Socket!");
    }
}
public void surfaceCreated(SurfaceHolder holder) {
    mCamera = Camera.open();
    try {
       mCamera.setPreviewDisplay(holder);
    } catch (IOException exception) {
        mCamera.release();
        mCamera = null;
        Log.e(tag, "Error settign Camera Preview Holder!");
    }
}
public void surfaceDestroyed(SurfaceHolder holder) {
    mCamera.setPreviewCallback(null);
    mCamera.stopPreview();
    udpSocket.close();
    mCamera.release();
    udpSocket = null;
    mCamera = null;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    Camera.Parameters parameters = mCamera.getParameters();
    parameters.setPreviewSize(WIDTH, HEIGHT);
    parameters.setPreviewFrameRate(FPS);
    parameters.setRotation(90);

    mCamera.setParameters(parameters);
    mCamera.setPreviewCallback(this);
    mCamera.startPreview();
}
/** Compresses the preview framer (data) into a JPEG image and send to a host at
 * the specified IPAddress and Port number for playback. Only sends frame if sendFrame
 * is true.
 * (non-Javadoc)
 * @see android.hardware.Camera.PreviewCallback#onPreviewFrame(byte[], android.hardware.Camera)
 * @see android.hardware.Camera
 */
public void onPreviewFrame(byte[] data, Camera camera) {
    final YuvImage imgPreview = new YuvImage(data, ImageFormat.NV21, WIDTH, HEIGHT, null);
    byte[] buffer;
    ByteArrayOutputStream jpegOutStream = new ByteArrayOutputStream();

    int offset = 0;
    int TotalLength, lengthLeft;
    DatagramPacket dgpout;
    // Compress image into JPEG
    imgPreview.compressToJpeg(new Rect(0, 0, imgPreview.getWidth(), imgPreview.getHeight()), quality, jpegOutStream);
    buffer = jpegOutStream.toByteArray();
    TotalLength = lengthLeft = buffer.length;
    // Send frame out. Split into packets of desired length.
    try {
        while(lengthLeft>packetSize){
            dgpout= new DatagramPacket(buffer, offset, packetSize);
            offset+=packetSize;
            lengthLeft-=packetSize;
            dgpout.setAddress(InetAddress.getByName(IPAddress));
            dgpout.setPort(PORT);
            udpSocket.send(dgpout);
        }
        if(lengthLeft>0){
            dgpout= new DatagramPacket(buffer,offset,lengthLeft);
            offset+=lengthLeft;
            lengthLeft-=lengthLeft;
            dgpout.setAddress(InetAddress.getByName(IPAddress));
            dgpout.setPort(PORT);
            udpSocket.send(dgpout);
        }
        Log.i(tag, "Sent Successfully: frame size="+TotalLength +"Buffer Size: "+udpSocket.getSendBufferSize());
    } catch (UnknownHostException e1) {
        Log.e(tag   , "UnknownHostException. Sending failed.");
    } catch (IOException e) {
        Log.e(tag   , "IOException. Sending failed.");
    }
}

}

А вот мой пример отладки для отправки только одного и того же JPEG снова и снова

if(sendFrame){
        sendFrame = false;
        final YuvImage imgPreview = new YuvImage(data, ImageFormat.NV21, WIDTH, HEIGHT, null);

        fixImage = data;
                byte[] buffer;
                ByteArrayOutputStream jpegOutStream = new ByteArrayOutputStream();

                int offset = 0;
                int TotalLength, lengthLeft;
                DatagramPacket dgpout;
                // Compress image into JPEG
                imgPreview.compressToJpeg(new Rect(0, 0, imgPreview.getWidth(), imgPreview.getHeight()), quality, jpegOutStream);
                buffer = jpegOutStream.toByteArray();

                fixJPEG = buffer;
                fixTotalLength = buffer.length;

    }
    int lengthLeft = 0;
    int offset = 0;
    DatagramPacket dgpout;
    if(fixImage==null || fixJPEG==null)
        return;
    /* Compress Optional */
    if(true){
        final YuvImage imgPreview = new YuvImage(fixImage, ImageFormat.NV21, WIDTH, HEIGHT, null);
        ByteArrayOutputStream jpegOutStream = new ByteArrayOutputStream();
        imgPreview.compressToJpeg(new Rect(0, 0, imgPreview.getWidth(), imgPreview.getHeight()), quality, jpegOutStream);
        fixJPEG = jpegOutStream.toByteArray();
    }
    fixTotalLength = lengthLeft = fixJPEG.length;
    // Send frame out. Split into packets of desired length.
    try {
        while(lengthLeft>packetSize){
            dgpout= new DatagramPacket(fixJPEG, offset, packetSize);
            offset+=packetSize;
            lengthLeft-=packetSize;
            dgpout.setAddress(InetAddress.getByName(IPAddress));
            dgpout.setPort(PORT);
            udpSocket.send(dgpout);
        }
        if(lengthLeft>0){
        dgpout= new DatagramPacket(fixJPEG,offset,lengthLeft);
            offset+=lengthLeft;
            lengthLeft-=lengthLeft;
            dgpout.setAddress(InetAddress.getByName(IPAddress));
            dgpout.setPort(PORT);
            udpSocket.send(dgpout);
        }
        Log.i(tag, "Sent Successfully: frame size="+fixTotalLength +"Buffer Size: "+udpSocket.getSendBufferSize());
    } catch (UnknownHostException e1) {
        Log.e(tag   , "UnknownHostException. Sending failed.");
    } catch (IOException e) {
        Log.e(tag   , "IOException. Sending failed.");
    }

У кого-нибудь есть идеи дляповышение эффективности?Это происходит на всех устройствах?Я использую Android 2.2.Любые идеи приветствуются.

* РЕДАКТИРОВАТЬ Добавлен весь класс предварительного просмотра

1 Ответ

2 голосов
/ 16 июля 2011

Вполне возможно, что Atrix (законно) игнорирует ваш запрос на изменение частоты кадров предварительного просмотра.

При обратном вызове surfaceChanged попытайтесь вызвать следующее и проверить значение в отладчике:

List<Integer> rates = parameters.getSupportedPreviewFrameRates();

Документация Android гласит:

Возвращает список поддерживаемых частот предварительного просмотра.null, если предварительная настройка частоты кадров не поддерживается.

Кроме того, в документах для setPreviewFrameRate() указано:

Это целевая частота кадров.Фактическая частота кадров зависит от драйвера.

Так что, возможно, Atrix не поддерживает ничего кроме 15 кадров в секунду для предварительного просмотра.

В любом случае, правильноеСпособ использования частоты кадров предварительного просмотра заключается в первом вызове getSupportedPreviewFrameRates().Если он возвращает ненулевой результат, найдите ближайший номер в списке к тому, что вы хотите, и передайте его setPreviewFrameRate().В противном случае вам придется жить с любой скоростью, поддерживаемой устройством.

...