void GStreamerReader::ImageDataFromVideoFrame(GstVideoFrame *aFrame, PlanarYCbCrImage::Data *aData) { NS_ASSERTION(GST_VIDEO_INFO_IS_YUV(&mVideoInfo), "Non-YUV video frame formats not supported"); NS_ASSERTION(GST_VIDEO_FRAME_N_COMPONENTS(aFrame) == 3, "Unsupported number of components in video frame"); aData->mPicX = aData->mPicY = 0; aData->mPicSize = gfx::IntSize(mPicture.width, mPicture.height); aData->mStereoMode = StereoMode::MONO; aData->mYChannel = GST_VIDEO_FRAME_COMP_DATA(aFrame, 0); aData->mYStride = GST_VIDEO_FRAME_COMP_STRIDE(aFrame, 0); aData->mYSize = gfx::IntSize(GST_VIDEO_FRAME_COMP_WIDTH(aFrame, 0), GST_VIDEO_FRAME_COMP_HEIGHT(aFrame, 0)); aData->mYSkip = GST_VIDEO_FRAME_COMP_PSTRIDE(aFrame, 0) - 1; aData->mCbCrStride = GST_VIDEO_FRAME_COMP_STRIDE(aFrame, 1); aData->mCbCrSize = gfx::IntSize(GST_VIDEO_FRAME_COMP_WIDTH(aFrame, 1), GST_VIDEO_FRAME_COMP_HEIGHT(aFrame, 1)); aData->mCbChannel = GST_VIDEO_FRAME_COMP_DATA(aFrame, 1); aData->mCrChannel = GST_VIDEO_FRAME_COMP_DATA(aFrame, 2); aData->mCbSkip = GST_VIDEO_FRAME_COMP_PSTRIDE(aFrame, 1) - 1; aData->mCrSkip = GST_VIDEO_FRAME_COMP_PSTRIDE(aFrame, 2) - 1; }
static inline guint _get_plane_height (GstVideoInfo * info, guint plane) { if (GST_VIDEO_INFO_IS_YUV (info)) /* For now component width and plane width are the same and the * plane-component mapping matches */ return GST_VIDEO_INFO_COMP_HEIGHT (info, plane); else /* RGB, GRAY */ return GST_VIDEO_INFO_HEIGHT (info); }
static gboolean gst_webp_enc_set_format (GstVideoEncoder * encoder, GstVideoCodecState * state) { GstWebpEnc *enc = GST_WEBP_ENC (encoder); GstVideoCodecState *output_state; GstVideoInfo *info; GstVideoFormat format; info = &state->info; format = GST_VIDEO_INFO_FORMAT (info); if (GST_VIDEO_INFO_IS_YUV (info)) { switch (format) { case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: enc->webp_color_space = WEBP_YUV420; break; default: break; } } else { if (GST_VIDEO_INFO_IS_RGB (info)) { enc->rgb_format = format; enc->use_argb = 1; } } if (enc->input_state) gst_video_codec_state_unref (enc->input_state); enc->input_state = gst_video_codec_state_ref (state); output_state = gst_video_encoder_set_output_state (GST_VIDEO_ENCODER (enc), gst_caps_new_empty_simple ("image/webp"), enc->input_state); gst_video_codec_state_unref (output_state); return TRUE; }
static gdouble gst_compare_ssim (GstCompare * comp, GstBuffer * buf1, GstCaps * caps1, GstBuffer * buf2, GstCaps * caps2) { GstVideoInfo info1, info2; GstVideoFrame frame1, frame2; gint i, comps; gdouble cssim[4], ssim, c[4] = { 1.0, 0.0, 0.0, 0.0 }; if (!caps1) goto invalid_input; if (!gst_video_info_from_caps (&info1, caps1)) goto invalid_input; if (!caps2) goto invalid_input; if (!gst_video_info_from_caps (&info2, caps1)) goto invalid_input; if (GST_VIDEO_INFO_FORMAT (&info1) != GST_VIDEO_INFO_FORMAT (&info2) || GST_VIDEO_INFO_WIDTH (&info1) != GST_VIDEO_INFO_WIDTH (&info2) || GST_VIDEO_INFO_HEIGHT (&info1) != GST_VIDEO_INFO_HEIGHT (&info2)) return comp->threshold + 1; comps = GST_VIDEO_INFO_N_COMPONENTS (&info1); /* note that some are reported both yuv and gray */ for (i = 0; i < comps; ++i) c[i] = 1.0; /* increase luma weight if yuv */ if (GST_VIDEO_INFO_IS_YUV (&info1) && (comps > 1)) c[0] = comps - 1; for (i = 0; i < comps; ++i) c[i] /= (GST_VIDEO_INFO_IS_YUV (&info1) && (comps > 1)) ? 2 * (comps - 1) : comps; gst_video_frame_map (&frame1, &info1, buf1, GST_MAP_READ); gst_video_frame_map (&frame2, &info2, buf2, GST_MAP_READ); for (i = 0; i < comps; i++) { gint cw, ch, step, stride; /* only support most common formats */ if (GST_VIDEO_INFO_COMP_DEPTH (&info1, i) != 8) goto unsupported_input; cw = GST_VIDEO_FRAME_COMP_WIDTH (&frame1, i); ch = GST_VIDEO_FRAME_COMP_HEIGHT (&frame1, i); step = GST_VIDEO_FRAME_COMP_PSTRIDE (&frame1, i); stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame1, i); GST_LOG_OBJECT (comp, "component %d", i); cssim[i] = gst_compare_ssim_component (comp, GST_VIDEO_FRAME_COMP_DATA (&frame1, i), GST_VIDEO_FRAME_COMP_DATA (&frame2, i), cw, ch, step, stride); GST_LOG_OBJECT (comp, "ssim[%d] = %f", i, cssim[i]); } gst_video_frame_unmap (&frame1); gst_video_frame_unmap (&frame2); #ifndef GST_DISABLE_GST_DEBUG for (i = 0; i < 4; i++) { GST_DEBUG_OBJECT (comp, "ssim[%d] = %f, c[%d] = %f", i, cssim[i], i, c[i]); } #endif ssim = cssim[0] * c[0] + cssim[1] * c[1] + cssim[2] * c[2] + cssim[3] * c[3]; return ssim; /* ERRORS */ invalid_input: { GST_ERROR_OBJECT (comp, "ssim method needs raw video input"); return 0; } unsupported_input: { GST_ERROR_OBJECT (comp, "raw video format not supported %" GST_PTR_FORMAT, caps1); return 0; } }
static void check_1x1_buffer (GstBuffer * buf, GstCaps * caps) { GstVideoInfo info; GstVideoFrame frame; /* the exact values we check for come from videotestsrc */ static const guint yuv_values[] = { 81, 90, 240, 255 }; static const guint rgb_values[] = { 0xff, 0, 0, 255 }; static const guint gray8_values[] = { 0x51 }; static const guint gray16_values[] = { 0x5151 }; const guint *values; guint i; const GstVideoFormatInfo *finfo; fail_unless (buf != NULL); fail_unless (caps != NULL); fail_unless (gst_video_info_from_caps (&info, caps)); fail_unless (gst_video_frame_map (&frame, &info, buf, GST_MAP_READ)); finfo = info.finfo; if (GST_VIDEO_INFO_IS_YUV (&info)) values = yuv_values; else if (GST_VIDEO_INFO_IS_GRAY (&info)) if (GST_VIDEO_FORMAT_INFO_BITS (finfo) == 8) values = gray8_values; else values = gray16_values; else values = rgb_values; GST_MEMDUMP ("buffer", GST_VIDEO_FRAME_PLANE_DATA (&frame, 0), 8); for (i = 0; i < GST_VIDEO_FRAME_N_COMPONENTS (&frame); i++) { guint8 *data = GST_VIDEO_FRAME_COMP_DATA (&frame, i); GST_DEBUG ("W: %d", GST_VIDEO_FORMAT_INFO_W_SUB (finfo, i)); GST_DEBUG ("H: %d", GST_VIDEO_FORMAT_INFO_H_SUB (finfo, i)); if (GST_VIDEO_FORMAT_INFO_W_SUB (finfo, i) >= GST_VIDEO_FRAME_WIDTH (&frame)) continue; if (GST_VIDEO_FORMAT_INFO_H_SUB (finfo, i) >= GST_VIDEO_FRAME_HEIGHT (&frame)) continue; if (GST_VIDEO_FORMAT_INFO_BITS (finfo) == 8) { fail_unless_equals_int (data[0], values[i]); } else if (GST_VIDEO_FORMAT_INFO_BITS (finfo) == 16) { guint16 pixels, val; gint depth; if (GST_VIDEO_FORMAT_INFO_IS_LE (finfo)) pixels = GST_READ_UINT16_LE (data); else pixels = GST_READ_UINT16_BE (data); depth = GST_VIDEO_FORMAT_INFO_DEPTH (finfo, i); val = pixels >> GST_VIDEO_FORMAT_INFO_SHIFT (finfo, i); val = val & ((1 << depth) - 1); GST_DEBUG ("val %08x %d : %d", pixels, i, val); if (depth <= 8) { fail_unless_equals_int (val, values[i] >> (8 - depth)); } else {
/* Called in the gl thread */ static gboolean _init_convert (GstGLColorConvert * convert) { GstGLFuncs *gl; gboolean res; struct ConvertInfo *info = &convert->priv->convert_info; gint i; gl = convert->context->gl_vtable; if (convert->initted) return TRUE; GST_INFO ("Initializing color conversion from %s to %s", gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&convert->in_info)), gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&convert->out_info))); if (!gl->CreateProgramObject && !gl->CreateProgram) { gst_gl_context_set_error (convert->context, "Cannot perform color conversion without OpenGL shaders"); goto error; } if (GST_VIDEO_INFO_IS_RGB (&convert->in_info)) { if (GST_VIDEO_INFO_IS_RGB (&convert->out_info)) { _RGB_to_RGB (convert); } } if (GST_VIDEO_INFO_IS_YUV (&convert->in_info)) { if (GST_VIDEO_INFO_IS_RGB (&convert->out_info)) { _YUV_to_RGB (convert); } } if (GST_VIDEO_INFO_IS_RGB (&convert->in_info)) { if (GST_VIDEO_INFO_IS_YUV (&convert->out_info)) { _RGB_to_YUV (convert); } } if (GST_VIDEO_INFO_IS_RGB (&convert->in_info)) { if (GST_VIDEO_INFO_IS_GRAY (&convert->out_info)) { _RGB_to_GRAY (convert); } } if (GST_VIDEO_INFO_IS_GRAY (&convert->in_info)) { if (GST_VIDEO_INFO_IS_RGB (&convert->out_info)) { _GRAY_to_RGB (convert); } } if (!info->frag_prog || info->in_n_textures == 0 || info->out_n_textures == 0) goto unhandled_format; /* multiple draw targets not supported on GLES2...yet */ if (info->out_n_textures > 1 && (!gl->DrawBuffers || USING_GLES2 (convert->context))) { g_free (info->frag_prog); GST_ERROR ("Conversion requires output to multiple draw buffers"); goto incompatible_api; } /* Requires reading from a RG/LA framebuffer... */ if (USING_GLES2 (convert->context) && (GST_VIDEO_INFO_FORMAT (&convert->out_info) == GST_VIDEO_FORMAT_YUY2 || GST_VIDEO_INFO_FORMAT (&convert->out_info) == GST_VIDEO_FORMAT_UYVY)) { g_free (info->frag_prog); GST_ERROR ("Conversion requires reading with an unsupported format"); goto incompatible_api; } res = gst_gl_context_gen_shader (convert->context, text_vertex_shader, info->frag_prog, &convert->shader); g_free (info->frag_prog); if (!res) goto error; convert->shader_attr_position_loc = gst_gl_shader_get_attribute_location (convert->shader, "a_position"); convert->shader_attr_texture_loc = gst_gl_shader_get_attribute_location (convert->shader, "a_texcoord"); gst_gl_shader_use (convert->shader); if (info->cms_offset && info->cms_coeff1 && info->cms_coeff2 && info->cms_coeff3) { gst_gl_shader_set_uniform_3fv (convert->shader, "offset", 1, info->cms_offset); gst_gl_shader_set_uniform_3fv (convert->shader, "coeff1", 1, info->cms_coeff1); gst_gl_shader_set_uniform_3fv (convert->shader, "coeff2", 1, info->cms_coeff2); gst_gl_shader_set_uniform_3fv (convert->shader, "coeff3", 1, info->cms_coeff3); } for (i = info->in_n_textures; i >= 0; i--) { if (info->shader_tex_names[i]) gst_gl_shader_set_uniform_1i (convert->shader, info->shader_tex_names[i], i); } gst_gl_shader_set_uniform_1f (convert->shader, "width", GST_VIDEO_INFO_WIDTH (&convert->in_info)); gst_gl_shader_set_uniform_1f (convert->shader, "height", GST_VIDEO_INFO_HEIGHT (&convert->in_info)); if (info->chroma_sampling[0] > 0.0f && info->chroma_sampling[1] > 0.0f) { gst_gl_shader_set_uniform_2fv (convert->shader, "chroma_sampling", 1, info->chroma_sampling); } gst_gl_context_clear_shader (convert->context); if (!_init_convert_fbo (convert)) { goto error; } gl->BindTexture (GL_TEXTURE_2D, 0); convert->initted = TRUE; return TRUE; unhandled_format: gst_gl_context_set_error (convert->context, "Don't know how to convert from %s to %s", gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&convert->in_info)), gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&convert->out_info))); error: return FALSE; incompatible_api: { gst_gl_context_set_error (convert->context, "Converting from %s to %s requires " "functionality that the current OpenGL setup does not support", gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&convert->in_info)), gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&convert->out_info))); return FALSE; } }