在GStreamer插件中准确定位流的(0,0)像素及获取正确尺寸与偏移
解决GStreamer插件中获取裁剪后视频缓冲区正确宽高与偏移的问题
你遇到的问题核心是:GST_VIDEO_FRAME_WIDTH(frame)和GST_VIDEO_FRAME_HEIGHT(frame)获取的是缓冲区的物理存储尺寸,而videocrop这类元素通常不会修改缓冲区内存大小,只是通过元数据标记出需要显示的有效区域,所以插件拿到的仍是原始500x500的缓冲区尺寸,但实际显示的是裁剪后的400x400区域。
以下是具体解决方法:
1. 提取裁剪元数据(GstVideoCropMeta)
标准videocrop会将裁剪信息以GstVideoCropMeta附加到缓冲区上,你可以直接从缓冲区中获取这个元数据来得到偏移和有效尺寸:
GstVideoCropMeta *crop_meta = gst_buffer_get_video_crop_meta(buffer);
如果crop_meta不为空,其中的字段对应:
crop_meta->x:有效区域左上角的水平偏移crop_meta->y:有效区域左上角的垂直偏移crop_meta->width:裁剪后的有效宽度crop_meta->height:裁剪后的有效高度
2. 结合Caps确认逻辑尺寸
你提到Caps能提供正确的宽高,这是因为Caps描述的是数据流的逻辑显示尺寸,和最终屏幕显示的一致。可以通过GstVideoInfo从Caps中解析出这些信息:
GstVideoInfo video_info; if (gst_video_info_from_caps(&video_info, caps)) { gint display_width = GST_VIDEO_INFO_WIDTH(&video_info); gint display_height = GST_VIDEO_INFO_HEIGHT(&video_info); }
通常crop_meta->width/height和Caps中的宽高是一致的,你可以任选一种方式获取,结合偏移量就能定位到缓冲区中的有效像素区域。
3. 定位有效像素的代码示例
假设你已经拿到GstVideoFrame和对应的Caps,完整的像素定位逻辑如下:
// 从Caps获取逻辑显示尺寸 GstVideoInfo video_info; gst_video_info_from_caps(&video_info, caps); gint display_w = GST_VIDEO_INFO_WIDTH(&video_info); gint display_h = GST_VIDEO_INFO_HEIGHT(&video_info); // 获取裁剪偏移 gint crop_x = 0, crop_y = 0; GstVideoCropMeta *crop_meta = gst_buffer_get_video_crop_meta(GST_VIDEO_FRAME_BUFFER(frame)); if (crop_meta != NULL) { crop_x = crop_meta->x; crop_y = crop_meta->y; } // 计算有效区域的起始像素地址 guchar *effective_pixels = GST_VIDEO_FRAME_PIXEL_DATA(frame) + crop_y * GST_VIDEO_FRAME_PITCH(frame) + crop_x * GST_VIDEO_FRAME_COMP_PSTRIDE(frame, 0); // 后续操作仅针对effective_pixels开始的display_w x display_h区域即可
注意事项
- 若使用非标准裁剪元素,可能不会生成
GstVideoCropMeta,此时需要检查该元素是否有自定义元数据格式。 - 原地修改缓冲区时,只需操作有效区域内的像素即可,裁剪掉的区域不会被下游元素渲染。
内容的提问来源于stack exchange,提问作者Maximilian
相关产品推荐
相关产品推荐

