2017-01-14 10 views
3

Проще говоря, все, что мне нужно сделать, это отобразить живой поток видеокадров в Android (каждый кадр - формат YUV420). У меня есть функция обратного вызова, где я получаю отдельные кадры в виде массива байтов. То, что выглядит следующим образом:Опции для эффективного рисования потока байт-массивов для отображения на Android

public void onFrameReceived(byte[] frame, int height, int width, int format) { 
    // display this frame to surfaceview/textureview. 
} 

Осуществимый но медленный вариант, чтобы преобразовать массив байтов в растровое изображение и рисовать на холсте на SurfaceView. В будущем я идеально хотел бы иметь возможность изменять яркость, контраст и т. Д. Этого кадра, и поэтому я надеюсь, что смогу использовать OpenGL-ES для этого. Каковы мои другие варианты, чтобы сделать это эффективно?

Помните, что в отличие от реализаций Camera или MediaPlayer класса, я не могу направить свой выход к SurfaceView/textureview с использованием camera.setPreviewTexture(surfaceTexture);, как я получаю отдельные кадры с использованием Gstreamer в С.

+0

Я пошел прямо по пути оказания YUV кадры непосредственно с OpenGLES. Я могу опубликовать фрагментарный шейдер и любой другой источник из моего кода, если это поможет. – WLGfx

+0

Как вам удалось отобразить эти кадры YUV именно то, что мне нужно знать! Получали ли вы эти кадры в виде байтового массива, как я? (Исходный код был бы полезен, спасибо!) –

ответ

1

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

Если кадр, например, равен 756 x 576, тогда кадр Y будет такого размера. Рамка U и V составляет половину ширины и высоты кадра Y, поэтому вам нужно будет убедиться, что вы учитываете различия в размерах.

Я не знаю об API-интерфейсе камеры, но кадры, которые я получаю от источника DVB, имеют ширину, а также каждая строка имеет шаг. Дополняет пиксели в конце каждой строки в кадре. На всякий случай, если у вас одинаковое, тогда учтите это при вычислении ваших координат текстуры.

Настройки координаты текстуры для учета ширины и шага (linesize):

float u = 1.0f/buffer->y_linesize * buffer->wid; // adjust texture coord for edge 

вершинного шейдера Я использовал принимает координаты экрана от 0.0 до 1.0, но вы можете изменить их в соответствии с. Он также принимает текстурные координаты и цветной вход. Я использовал ввод цвета, так что можно добавить выцветанию и т.д.

вершинного шейдера:

#ifdef GL_ES 
precision mediump float; 
const float c1 = 1.0; 
const float c2 = 2.0; 
#else 
const float c1 = 1.0f; 
const float c2 = 2.0f; 
#endif 

attribute vec4 a_vertex; 
attribute vec2 a_texcoord; 
attribute vec4 a_colorin; 
varying vec2 v_texcoord; 
varying vec4 v_colorout; 



void main(void) 
{ 
    v_texcoord = a_texcoord; 
    v_colorout = a_colorin; 

    float x = a_vertex.x * c2 - c1; 
    float y = -(a_vertex.y * c2 - c1); 

    gl_Position = vec4(x, y, a_vertex.z, c1); 
} 

фрагмент шейдера, который принимает три однородные текстуры, по одному для каждого framges и преобразует Y, U и V к RGB. Это также умножает цвет передается из вершинного шейдера:

#ifdef GL_ES 
precision mediump float; 
#endif 

uniform sampler2D u_texturey; 
uniform sampler2D u_textureu; 
uniform sampler2D u_texturev; 
varying vec2 v_texcoord; 
varying vec4 v_colorout; 

void main(void) 
{ 
    float y = texture2D(u_texturey, v_texcoord).r; 
    float u = texture2D(u_textureu, v_texcoord).r - 0.5; 
    float v = texture2D(u_texturev, v_texcoord).r - 0.5; 
    vec4 rgb = vec4(y + 1.403 * v, 
        y - 0.344 * u - 0.714 * v, 
        y + 1.770 * u, 
        1.0); 
    gl_FragColor = rgb * v_colorout; 
} 

Вершины, используемая в:

float x, y, z; // coords 
float s, t;  // texture coords 
uint8_t r, g, b, a; // colour and alpha 

Надеется, что это помогает!

EDIT:

Для формата NV12 вы можете использовать фрагмент шейдеров, хотя я не пробовал сам. Он принимает чередующийся УФ-излучение как канал яркости-альфа или аналогичный.

Смотрите здесь, как один человек ответил на это: https://stackoverflow.com/a/22456885/2979092

+0

Мой первоначальный вопрос состоял в том, как эти байт-рамки будут отображаться на поверхности (фактический механизм того, как будет рисоваться рамка). Поэтому я не могу принять это как ответ. Однако это полезно! Большое спасибо. Истинный формат, в котором находятся мои кадры, - NV12. (УФ-компоненты чередуются). Вы знаете, как я буду извлекать компоненты U и V отдельно? –

+0

Я добавил редактирование со ссылкой на ответ шейдера NV12. – WLGfx

+0

Да, я закончил тем, что использовал это. Еще раз спасибо! Я выложу свое решение о том, как эффективно отображать отдельные байт-рамки для текстуры. Я, тем не менее, поддержу ваш ответ, поскольку это было очень полезно, как только у меня хватило репутации, чтобы сделать это! –

 Смежные вопросы

  • Нет связанных вопросов^_^