I made some progress with openMax but I block in rendering on the texture. In the example they use eglCreateImageKHR, I read the doc but I didn't really undestand how it work like how can it display on the screen without texture ...
Code: Select all
void componentOMX::readVideo(void* arg){
int err;
if(eglImage == 0){
std::cerr << "eglImage is null.\n";
exit(1);
}
err = ilclient_enable_port_buffers(decodeComponent, 130, NULL, NULL, NULL);
if(err < 0){
std::cerr << "couldn't enable buffers" << std::endl;
return;
}
ilclient_enable_port(decodeComponent, 130);
err = ilclient_change_component_state(decodeComponent, OMX_StateExecuting);
if(err < 0){
std::cerr << "couldn't change state to Executing" << std::endl;
return;
}
config.setDecoderConfig(decodeComponent, demux.getExtradataSize(), demux.getExtradata());
config.setClockState(clockComponent);
AVPacket pkt = demux.getPacket();
while(av_read_frame(demux.getContext(), &pkt) >= 0){
AVPacket origPacket = pkt;
if(pkt.stream_index == demux.getVideoIndex()){
omxBuffer = ilclient_get_input_buffer(decodeComponent, 130, 1);
if(omxBuffer != NULL)
config.copyInBufferAndEmpty(&pkt, decodeComponent, omxBuffer, demux.getTimebase());
err = ilclient_wait_for_event(decodeComponent, OMX_EventPortSettingsChanged, 131, 0, 0, 1, ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 0);
if(err >= 0)
break;
if(ilclient_remove_event(decodeComponent, OMX_EventPortSettingsChanged, 131, 0, 0, 1) == 0){
break;
}
}
av_free_packet(&origPacket);
// pkt = demux.getPacket();
}
TUNNEL_T decodeTunnel;
set_tunnel(&decodeTunnel, decodeComponent, 131, schedulerComponent, 10);
if( (err = ilclient_setup_tunnel(&decodeTunnel, 0, 0)) < 0){
std::cerr << "error setting up decode tunnel" << std::endl;
return;
}
TUNNEL_T schedulerTunnel;
set_tunnel(&schedulerTunnel, schedulerComponent, 11, renderComponent, 220);//90);
if( (err = ilclient_setup_tunnel(&schedulerTunnel, 0, 1000)) < 0){
std::cerr << "error setting up scheduler tunnel" << std::endl;
return;
}
TUNNEL_T clockTunnel;
set_tunnel(&clockTunnel, clockComponent, 80, schedulerComponent, 12);
if( (err = ilclient_setup_tunnel(&clockTunnel, 0, 0)) < 0){
std::cerr << "error setting up clock tunnel" << std::endl;
return;
}
else
ilclient_change_component_state(clockComponent, OMX_StateExecuting);
OMX_SendCommand(ilclient_get_handle(decodeComponent), OMX_CommandPortEnable, 131, NULL);
ilclient_enable_port(decodeComponent, 131);
OMX_SendCommand(ilclient_get_handle(clockComponent), OMX_CommandPortEnable, 80, NULL);
ilclient_enable_port(clockComponent, 80);
OMX_SendCommand(ilclient_get_handle(schedulerComponent), OMX_CommandPortEnable, 10, NULL);
ilclient_enable_port(schedulerComponent, 10);
OMX_SendCommand(ilclient_get_handle(schedulerComponent), OMX_CommandPortEnable, 11, NULL);
ilclient_enable_port(schedulerComponent, 11);
OMX_SendCommand(ilclient_get_handle(schedulerComponent), OMX_CommandPortEnable, 12, NULL);
ilclient_enable_port(schedulerComponent, 12);
// OMX_SendCommand(ilclient_get_handle(renderComponent), OMX_CommandPortEnable, 221, NULL);
// ilclient_enable_port(renderComponent, 221);
err = ilclient_change_component_state(decodeComponent, OMX_StateExecuting);
if(err < 0){
std::cerr << "couldn't change state to Executing" << std::endl;
return ;
}
// err = ilclient_change_component_state(renderComponent, OMX_StateExecuting);
// if(err < 0){
// std::cerr << "couldn't change state to Executing" << std::endl;
// return ;
// }
err = ilclient_change_component_state(schedulerComponent, OMX_StateExecuting);
if(err < 0){
std::cerr << "couldn't change state to Executing" << std::endl;
return ;
}
err = ilclient_change_component_state(clockComponent, OMX_StateExecuting);
if(err < 0){
std::cerr << "couldn't change state to Executing" << std::endl;
return ;
}
// av_seek_frame(demux.getContext(), demux.getVideoIndex(), 0, AVSEEK_FLAG_BACKWARD);
while(1){
while(av_read_frame(demux.getContext(), &pkt) >= 0){
if(pkt.stream_index != demux.getVideoIndex())
continue;
omxBuffer = ilclient_get_input_buffer(decodeComponent, 130, 1);
if(omxBuffer != NULL)
config.copyInBufferAndEmpty(&pkt, decodeComponent, omxBuffer, demux.getTimebase());
err = ilclient_wait_for_event(decodeComponent, OMX_EventPortSettingsChanged, 131, 0, 0, 1, ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 10000);
if(err >= 0)
std::cerr << "Another port setting change" << std::endl;
if(ilclient_setup_tunnel(&schedulerTunnel, 0, 1000) != 0){
break;
}
err = ilclient_change_component_state(renderComponent, OMX_StateIdle);
if (OMX_SendCommand(ilclient_get_handle(renderComponent), OMX_CommandPortEnable, 221, NULL) != OMX_ErrorNone){
printf("OMX_CommandPortEnable failed.\n");
exit(1);
}
if (OMX_UseEGLImage(ILC_GET_HANDLE(renderComponent), &omxBuffer, 221, NULL, eglImage) != OMX_ErrorNone){
std::cerr << "OMX_UseEGLImage failed.\n";
exit(1);
}
ilclient_change_component_state(renderComponent, OMX_StateExecuting);
if(err < 0){
std::cerr << "couldn't change state to Executing for EGLRENDER" << std::endl;
return ;
}
glUniformMatrix4fv(glGetUniformLocation(pIdVideos, "projection"), 1, GL_FALSE, glm::value_ptr(projectionVideos));
glUniformMatrix4fv(glGetUniformLocation(pIdVideos, "view"), 1, GL_FALSE, glm::value_ptr(viewVideos));
glUniformMatrix4fv(glGetUniformLocation(pIdVideos, "model"), 1, GL_FALSE, glm::value_ptr(modelVideos));
}
av_seek_frame(demux.getContext(), demux.getVideoIndex(), 0, 0);
}
ilclient_wait_for_event(renderComponent, OMX_EventBufferFlag, 90, 0, OMX_BUFFERFLAG_EOS, 0, ILCLIENT_BUFFER_FLAG_EOS, 10000);
return;
}
void componentOMX::videoToTexture(EGLDisplay display, EGLContext context, glm::mat4 projection, glm::mat4 view, GLint pIdVideo){
pIdVideos = pIdVideo;
projectionVideos = projectionVideos;
viewVideos = view;
GLint tex0 = glGetUniformLocation(pIdVideos, "texture0");
if(tex0 < 0){
std::cerr << "texture video failed..." << std::endl;
return;
}
int size = demux.getWidth() * demux.getHeight() * 4;
unsigned char* pix = new unsigned char[size];
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, demux.getWidth(), demux.getHeight(), 0,
GL_RGBA, GL_UNSIGNED_BYTE, pix);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
std::cerr << "wezsh weseh" << std::endl;
if(display == NULL){
std::cerr << "display is null\n";
exit(1);
}
if(context == NULL){
std::cerr << "context is null\n";
exit(1);
}
eglImage = eglCreateImageKHR(
display,
context,
EGL_GL_TEXTURE_2D_KHR,
(EGLClientBuffer)tex,
0);
if(eglImage != EGL_NO_IMAGE_KHR)
std::cerr << "mouais ..." << std::endl;
glUseProgram(pIdVideos);
glUniform1i(tex0, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
drawQuad->draw();
// glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, eglImage);
readVideo(eglImage);
// std::thread thread1(&componentOMX::readVideo, this, eglImage);
glBindTexture(GL_TEXTURE_2D, 0);
//std::cerr << "....." << std::endl;
glUseProgram(0);
// thread1.join();
}