static void update_image (APP_STATE_T * state, GstBuffer * buffer) { GstVideoGLTextureUploadMeta *meta = NULL; if (state->current_buffer) { gst_buffer_unref (state->current_buffer); } else { /* Setup the model world */ init_model_proj (state); TRACE_VC_MEMORY ("after init_model_proj"); /* initialize the OGLES texture(s) */ init_textures (state, buffer); TRACE_VC_MEMORY ("after init_textures"); } state->current_buffer = gst_buffer_ref (buffer); TRACE_VC_MEMORY_ONCE_FOR_ID ("before GstVideoGLTextureUploadMeta", gid0); if (state->can_avoid_upload) { GstMemory *mem = gst_buffer_peek_memory (state->current_buffer, 0); g_assert (gst_is_gl_memory (mem)); state->tex = ((GstGLMemory *) mem)->tex_id; } else if ((meta = gst_buffer_get_video_gl_texture_upload_meta (buffer))) { if (meta->n_textures == 1) { guint ids[4] = { state->tex, 0, 0, 0 }; if (!gst_video_gl_texture_upload_meta_upload (meta, ids)) { GST_WARNING ("failed to upload to texture"); } } } TRACE_VC_MEMORY_ONCE_FOR_ID ("after GstVideoGLTextureUploadMeta", gid1); }
void MediaPlayerPrivateGStreamerBase::updateTexture(GstBuffer* buffer) { if (!m_texture) return; if (!client()) return; const void* srcData = 0; #ifdef GST_API_VERSION_1 GRefPtr<GstCaps> caps = currentVideoSinkCaps(); #else GRefPtr<GstCaps> caps = GST_BUFFER_CAPS(buffer); #endif if (!caps) return; IntSize size; GstVideoFormat format; int pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride; if (!getVideoSizeAndFormatFromCaps(caps.get(), size, format, pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride)) return; if (m_texture->size() != size) m_texture->reset(size); #if GST_CHECK_VERSION(1, 1, 0) GstVideoGLTextureUploadMeta* meta; if ((meta = gst_buffer_get_video_gl_texture_upload_meta(buffer))) { if (meta->n_textures == 1) { // BRGx & BGRA formats use only one texture. const BitmapTextureGL* textureGL = static_cast<const BitmapTextureGL*>(m_texture.get()); guint ids[4] = { textureGL->id(), 0, 0, 0 }; if (gst_video_gl_texture_upload_meta_upload(meta, ids)) { client()->setPlatformLayerNeedsDisplay(); return; } } } #endif #ifdef GST_API_VERSION_1 GstMapInfo srcInfo; gst_buffer_map(buffer, &srcInfo, GST_MAP_READ); srcData = srcInfo.data; #else srcData = GST_BUFFER_DATA(buffer); #endif m_texture->updateContents(srcData, WebCore::IntRect(WebCore::IntPoint(0, 0), size), WebCore::IntPoint(0, 0), stride, BitmapTexture::UpdateCannotModifyOriginalImageData); #ifdef GST_API_VERSION_1 gst_buffer_unmap(buffer, &srcInfo); #endif client()->setPlatformLayerNeedsDisplay(); }
gboolean gst_buffer_ensure_texture_upload_meta (GstBuffer * buffer) { GstVideoGLTextureUploadMeta *const meta = gst_buffer_get_video_gl_texture_upload_meta (buffer); return meta ? meta_texture_ensure_info_from_buffer (meta->user_data, buffer) : gst_buffer_add_texture_upload_meta (buffer); }
PassRefPtr<BitmapTexture> MediaPlayerPrivateGStreamerBase::updateTexture(TextureMapper* textureMapper) { WTF::GMutexLocker<GMutex> lock(m_sampleMutex); if (!GST_IS_SAMPLE(m_sample.get())) return nullptr; GstCaps* caps = gst_sample_get_caps(m_sample.get()); if (!caps) return nullptr; GstVideoInfo videoInfo; gst_video_info_init(&videoInfo); if (!gst_video_info_from_caps(&videoInfo, caps)) return nullptr; IntSize size = IntSize(GST_VIDEO_INFO_WIDTH(&videoInfo), GST_VIDEO_INFO_HEIGHT(&videoInfo)); RefPtr<BitmapTexture> texture = textureMapper->acquireTextureFromPool(size, GST_VIDEO_INFO_HAS_ALPHA(&videoInfo) ? BitmapTexture::SupportsAlpha : BitmapTexture::NoFlag); GstBuffer* buffer = gst_sample_get_buffer(m_sample.get()); #if GST_CHECK_VERSION(1, 1, 0) GstVideoGLTextureUploadMeta* meta; if ((meta = gst_buffer_get_video_gl_texture_upload_meta(buffer))) { if (meta->n_textures == 1) { // BRGx & BGRA formats use only one texture. const BitmapTextureGL* textureGL = static_cast<const BitmapTextureGL*>(texture.get()); guint ids[4] = { textureGL->id(), 0, 0, 0 }; if (gst_video_gl_texture_upload_meta_upload(meta, ids)) return texture; } } #endif // Right now the TextureMapper only supports chromas with one plane ASSERT(GST_VIDEO_INFO_N_PLANES(&videoInfo) == 1); GstVideoFrame videoFrame; if (!gst_video_frame_map(&videoFrame, &videoInfo, buffer, GST_MAP_READ)) return nullptr; int stride = GST_VIDEO_FRAME_PLANE_STRIDE(&videoFrame, 0); const void* srcData = GST_VIDEO_FRAME_PLANE_DATA(&videoFrame, 0); texture->updateContents(srcData, WebCore::IntRect(WebCore::IntPoint(0, 0), size), WebCore::IntPoint(0, 0), stride, BitmapTexture::UpdateCannotModifyOriginalImageData); gst_video_frame_unmap(&videoFrame); return texture; }
void MediaPlayerPrivateGStreamerBase::updateTexture(GstBuffer* buffer) { if (!m_texture) return; if (!client()) return; const void* srcData = 0; IntSize size = naturalSize(); if (m_texture->size() != size) m_texture->reset(size); #if GST_CHECK_VERSION(1, 1, 0) GstVideoGLTextureUploadMeta* meta; if ((meta = gst_buffer_get_video_gl_texture_upload_meta(buffer))) { if (meta->n_textures == 1) { // BRGx & BGRA formats use only one texture. const BitmapTextureGL* textureGL = static_cast<const BitmapTextureGL*>(m_texture.get()); guint ids[4] = { textureGL->id(), 0, 0, 0 }; if (gst_video_gl_texture_upload_meta_upload(meta, ids)) { client()->setPlatformLayerNeedsDisplay(); return; } } } #endif #ifdef GST_API_VERSION_1 GstMapInfo srcInfo; gst_buffer_map(buffer, &srcInfo, GST_MAP_READ); srcData = srcInfo.data; #else srcData = GST_BUFFER_DATA(buffer); #endif m_texture->updateContents(srcData, WebCore::IntRect(WebCore::IntPoint(0, 0), size), WebCore::IntPoint(0, 0), size.width() * 4, BitmapTexture::UpdateCannotModifyOriginalImageData); #ifdef GST_API_VERSION_1 gst_buffer_unmap(buffer, &srcInfo); #endif client()->setPlatformLayerNeedsDisplay(); }
PassRefPtr<BitmapTexture> MediaPlayerPrivateGStreamerBase::updateTexture(TextureMapper* textureMapper) { g_mutex_lock(m_bufferMutex); if (!m_buffer) { g_mutex_unlock(m_bufferMutex); return 0; } const void* srcData = 0; #ifdef GST_API_VERSION_1 GRefPtr<GstCaps> caps = currentVideoSinkCaps(); #else GRefPtr<GstCaps> caps = GST_BUFFER_CAPS(m_buffer); #endif if (!caps) { g_mutex_unlock(m_bufferMutex); return 0; } IntSize size; GstVideoFormat format; int pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride; if (!getVideoSizeAndFormatFromCaps(caps.get(), size, format, pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride)) { g_mutex_unlock(m_bufferMutex); return 0; } RefPtr<BitmapTexture> texture = textureMapper->acquireTextureFromPool(size); #if GST_CHECK_VERSION(1, 1, 0) GstVideoGLTextureUploadMeta* meta; if ((meta = gst_buffer_get_video_gl_texture_upload_meta(m_buffer))) { if (meta->n_textures == 1) { // BRGx & BGRA formats use only one texture. const BitmapTextureGL* textureGL = static_cast<const BitmapTextureGL*>(texture.get()); guint ids[4] = { textureGL->id(), 0, 0, 0 }; if (gst_video_gl_texture_upload_meta_upload(meta, ids)) { g_mutex_unlock(m_bufferMutex); return texture; } } } #endif #ifdef GST_API_VERSION_1 GstMapInfo srcInfo; gst_buffer_map(m_buffer, &srcInfo, GST_MAP_READ); srcData = srcInfo.data; #else srcData = GST_BUFFER_DATA(m_buffer); #endif texture->updateContents(srcData, WebCore::IntRect(WebCore::IntPoint(0, 0), size), WebCore::IntPoint(0, 0), stride, BitmapTexture::UpdateCannotModifyOriginalImageData); #ifdef GST_API_VERSION_1 gst_buffer_unmap(m_buffer, &srcInfo); #endif g_mutex_unlock(m_bufferMutex); return texture; }
/** * gst_gl_filter_filter_texture: * @filter: a #GstGLFilter * @inbuf: an input buffer * @outbuf: an output buffer * * Perform automatic upload if needed, call filter_texture vfunc and then an * automatic download if needed. * * Returns: whether the transformation succeeded */ gboolean gst_gl_filter_filter_texture (GstGLFilter * filter, GstBuffer * inbuf, GstBuffer * outbuf) { GstGLFilterClass *filter_class; guint in_tex, out_tex; GstVideoFrame out_frame; gboolean ret, out_gl_mem; GstVideoGLTextureUploadMeta *out_tex_upload_meta; filter_class = GST_GL_FILTER_GET_CLASS (filter); if (!gst_gl_upload_perform_with_buffer (filter->upload, inbuf, &in_tex)) return FALSE; if (!gst_video_frame_map (&out_frame, &filter->out_info, outbuf, GST_MAP_WRITE | GST_MAP_GL)) { ret = FALSE; goto inbuf_error; } out_gl_mem = gst_is_gl_memory (out_frame.map[0].memory); out_tex_upload_meta = gst_buffer_get_video_gl_texture_upload_meta (outbuf); if (out_gl_mem) { out_tex = *(guint *) out_frame.data[0]; } else { GST_LOG ("Output Buffer does not contain correct memory, " "attempting to wrap for download"); if (!filter->download) { filter->download = gst_gl_download_new (filter->context); if (!gst_gl_download_init_format (filter->download, GST_VIDEO_FRAME_FORMAT (&out_frame), GST_VIDEO_FRAME_WIDTH (&out_frame), GST_VIDEO_FRAME_HEIGHT (&out_frame))) { GST_ELEMENT_ERROR (filter, RESOURCE, NOT_FOUND, ("%s", "Failed to init download format"), (NULL)); ret = FALSE; goto error; } } out_tex = filter->out_tex_id; } GST_DEBUG ("calling filter_texture with textures in:%i out:%i", in_tex, out_tex); g_assert (filter_class->filter_texture); ret = filter_class->filter_texture (filter, in_tex, out_tex); if (!out_gl_mem && !out_tex_upload_meta) { if (!gst_gl_download_perform_with_data (filter->download, out_tex, out_frame.data)) { GST_ELEMENT_ERROR (filter, RESOURCE, NOT_FOUND, ("%s", "Failed to download video frame"), (NULL)); ret = FALSE; goto error; } } error: gst_video_frame_unmap (&out_frame); inbuf_error: gst_gl_upload_release_buffer (filter->upload); return ret; }
/** * gst_gl_upload_perform_with_buffer: * @upload: a #GstGLUpload * @buffer: a #GstBuffer * @tex_id: resulting texture * * Uploads @buffer to the texture given by @tex_id. @tex_id is valid * until gst_gl_upload_release_buffer() is called. * * Returns: whether the upload was successful */ gboolean gst_gl_upload_perform_with_buffer (GstGLUpload * upload, GstBuffer * buffer, guint * tex_id) { GstMemory *mem; GstVideoGLTextureUploadMeta *gl_tex_upload_meta; guint texture_ids[] = { 0, 0, 0, 0 }; gint i; gboolean ret; g_return_val_if_fail (upload != NULL, FALSE); g_return_val_if_fail (buffer != NULL, FALSE); g_return_val_if_fail (tex_id != NULL, FALSE); g_return_val_if_fail (gst_buffer_n_memory (buffer) > 0, FALSE); gst_gl_upload_release_buffer (upload); /* GstGLMemory */ mem = gst_buffer_peek_memory (buffer, 0); if (gst_is_gl_memory (mem)) { if (GST_VIDEO_INFO_FORMAT (&upload->in_info) == GST_VIDEO_FORMAT_RGBA) { GstMapInfo map_info; gst_memory_map (mem, &map_info, GST_MAP_READ | GST_MAP_GL); gst_memory_unmap (mem, &map_info); *tex_id = ((GstGLMemory *) mem)->tex_id; return TRUE; } GST_LOG_OBJECT (upload, "Attempting upload with GstGLMemory"); for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&upload->in_info); i++) { upload->in_tex[i] = (GstGLMemory *) gst_buffer_peek_memory (buffer, i); } ret = _upload_memory (upload); *tex_id = upload->out_tex->tex_id; for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&upload->in_info); i++) { upload->in_tex[i] = NULL; } return ret; } #if GST_GL_HAVE_PLATFORM_EGL if (!upload->priv->tex_id && gst_is_egl_image_memory (mem)) gst_gl_context_gen_texture (upload->context, &upload->priv->tex_id, GST_VIDEO_FORMAT_RGBA, 0, 0); #endif if (!upload->priv->tex_id) gst_gl_context_gen_texture (upload->context, &upload->priv->tex_id, GST_VIDEO_FORMAT_RGBA, GST_VIDEO_INFO_WIDTH (&upload->in_info), GST_VIDEO_INFO_HEIGHT (&upload->in_info)); /* GstVideoGLTextureUploadMeta */ gl_tex_upload_meta = gst_buffer_get_video_gl_texture_upload_meta (buffer); if (gl_tex_upload_meta) { GST_LOG_OBJECT (upload, "Attempting upload with " "GstVideoGLTextureUploadMeta"); texture_ids[0] = upload->priv->tex_id; if (!gst_gl_upload_perform_with_gl_texture_upload_meta (upload, gl_tex_upload_meta, texture_ids)) { GST_DEBUG_OBJECT (upload, "Upload with GstVideoGLTextureUploadMeta " "failed"); } else { upload->priv->mapped = FALSE; *tex_id = upload->priv->tex_id; return TRUE; } } GST_LOG_OBJECT (upload, "Attempting upload with raw data"); /* GstVideoMeta map */ if (!gst_video_frame_map (&upload->priv->frame, &upload->in_info, buffer, GST_MAP_READ)) { GST_ERROR_OBJECT (upload, "Failed to map memory"); return FALSE; } upload->priv->mapped = TRUE; /* update the video info from the one updated by frame_map using video meta */ gst_gl_upload_set_format (upload, &upload->priv->frame.info); if (!gst_gl_upload_perform_with_data (upload, tex_id, upload->priv->frame.data)) { return FALSE; } return TRUE; }