int TexDirectVIV (GLenum Target, GLsizei Width, GLsizei Height, GLenum Format, GLvoid **Logical) { glTexDirectVIV (Target, Width, Height, Format, Logical); return glGetError (); }
static gboolean gst_imx_egl_viv_sink_gles2_renderer_fill_texture(GstImxEglVivSinkGLES2Renderer *renderer, GstBuffer *buffer) { GstVideoMeta *video_meta; GstMapInfo map_info; guint num_extra_lines, stride[3], offset[3], is_phys_buf; GstImxPhysMemMeta *phys_mem_meta; GstVideoFormat fmt; GLenum gl_format; GLuint w, h, total_w, total_h; phys_mem_meta = NULL; fmt = renderer->video_info.finfo->format; gl_format = gst_imx_egl_viv_sink_gles2_renderer_get_viv_format(fmt); w = renderer->video_info.width; h = renderer->video_info.height; phys_mem_meta = GST_IMX_PHYS_MEM_META_GET(buffer); is_phys_buf = (phys_mem_meta != NULL) && (phys_mem_meta->phys_addr != 0); /* Get the stride and number of extra lines */ video_meta = gst_buffer_get_video_meta(buffer); if (video_meta != NULL) { for (guint i = 0; i < MIN(video_meta->n_planes, 3); ++i) { stride[i] = video_meta->stride[i]; offset[i] = video_meta->offset[i]; } } else { for (guint i = 0; i < MIN(GST_VIDEO_INFO_N_PLANES(&(renderer->video_info)), 3); ++i) { stride[i] = GST_VIDEO_INFO_PLANE_STRIDE(&(renderer->video_info), i); offset[i] = GST_VIDEO_INFO_PLANE_OFFSET(&(renderer->video_info), i); } } num_extra_lines = is_phys_buf ? (phys_mem_meta->padding / stride[0]) : 0; /* stride is in bytes, we need pixels */ total_w = stride[0] / gst_imx_egl_viv_sink_gles2_renderer_bpp(fmt); total_h = h + num_extra_lines; GST_LOG("w/h: %d/%d total_w/h: %d/%d", w, h, total_w, total_h); glUniform2f(renderer->uv_scale_uloc, (float)w / (float)total_w, (float)h / (float)total_h); /* Only update texture if the video frame actually changed */ if ((renderer->viv_planes[0] == NULL) || (renderer->video_info_updated)) { GST_LOG("video frame did change"); if (is_phys_buf) { GLvoid *virt_addr; GLuint phys_addr; phys_addr = (GLuint)(phys_mem_meta->phys_addr); GST_LOG("mapping physical address 0x%x of video frame in buffer %p into VIV texture", phys_addr, (gpointer)buffer); gst_buffer_map(buffer, &map_info, GST_MAP_READ); virt_addr = map_info.data; /* Just set to make sure the == NULL check above is false */ renderer->viv_planes[0] = virt_addr; glTexDirectVIVMap( GL_TEXTURE_2D, total_w, total_h, gl_format, (GLvoid **)(&virt_addr), &phys_addr ); gst_buffer_unmap(buffer, &map_info); GST_LOG("done showing frame in buffer %p with virtual address %p physical address 0x%x", (gpointer)buffer, virt_addr, phys_addr); if (!gst_imx_egl_viv_sink_gles2_renderer_check_gl_error("render", "glTexDirectVIVMap")) return FALSE; } else { glTexDirectVIV( GL_TEXTURE_2D, total_w, total_h, gl_format, (GLvoid **) &(renderer->viv_planes) ); if (!gst_imx_egl_viv_sink_gles2_renderer_check_gl_error("render", "glTexDirectVIV")) return FALSE; GST_LOG("copying pixels into VIV direct texture buffer"); gst_buffer_map(buffer, &map_info, GST_MAP_READ); switch (fmt) { case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: memcpy(renderer->viv_planes[0], map_info.data + offset[0], stride[0] * total_h); memcpy(renderer->viv_planes[1], map_info.data + offset[1], stride[1] * total_h / 2); memcpy(renderer->viv_planes[2], map_info.data + offset[2], stride[2] * total_h / 2); break; case GST_VIDEO_FORMAT_NV12: case GST_VIDEO_FORMAT_NV21: memcpy(renderer->viv_planes[0], map_info.data + offset[0], stride[0] * total_h); memcpy(renderer->viv_planes[1], map_info.data + offset[1], stride[1] * total_h / 2); break; default: memcpy(renderer->viv_planes[0], map_info.data, stride[0] * total_h); } gst_buffer_unmap(buffer, &map_info); } glTexDirectInvalidateVIV(GL_TEXTURE_2D); if (!gst_imx_egl_viv_sink_gles2_renderer_check_gl_error("render", "glTexDirectInvalidateVIV")) return FALSE; renderer->video_info_updated = FALSE; } else { GST_LOG("video frame did not change - not doing anything"); } return TRUE; }