ios - GStreamer iOS - 返回到相应的 UITabBarController 选项卡时可能出现流式传输和 glimagesink 阻塞问题
问题描述
在连接到 iPhone 8+ 13.5.1 GST Ver: 1.16.1 的 Mac Catalina 10.15.6 上运行 XCode 12.0 beta 6
我已经创建了一个应用程序,它使用 rtsp 视频流作为 GStreamer 管道在动态创建的 UI 的选项卡视图上显示流的功能之一。当切换到流选项卡并第一次启动流时,它会启动,gstreamer 和 ios 很好,流是可见的。在切换到 UI 视图和窗口句柄失焦的另一个选项卡后,我将来自解码器的样本丢弃到管道中的 appsink 元素(下面将详细介绍)。
切换回流式传输选项卡,我恢复流式传输,我可以看出有视频数据进入(如下所述),但没有显示。
整个流有 2 个管道,分别由 appsink 和 appsrc 分隔。我可以告诉视频数据在切换回选项卡后进入,因为我注册的应用程序“新样本”回调被调用。此外,在回调中,使用 gst_app_src_push_sample(...) 将样本推送到 appsrc 元素会返回而不会出错。
这是管道外观的示例:
rtspsrc 名称=rtspsrc01 位置=rtsp://192.168.0.25:7768/流延迟=25 !rtph264depay!h264解析!解码器!视频转换!视频框左=0 右=0 上=0 下=0 !三通名称=t2_01!队列 !视频缩放!glimagesink 名称=thumb_sink01 t2_01。!应用程序名称 = appsink01 同步 = 假
应用程序名称=appsrc01 最大延迟=10 !视频缩放!glimagesink 名称=viewer_sink01 同步=false
名为“thumb_sink01”的 glimagesink 元素是选项卡上显示的流的缩略图视图,“appsink01”转到“new-sample”回调。
第二个管道上的“appsrc01”元素正在从 gst_app_src_push_sample(...) 调用接收样本,并转到同一选项卡上更大的 UIImageView 窗口。
在切换回流选项卡后,我可以看到内存消耗也在增加,因此第二个管道上的元素之一似乎由于某种原因而阻塞。我已经验证了两个管道也都处于 GST_STATE_PLAYING 状态。
我已经尝试了很多其他的事情,例如验证 GStreamer 正在渲染的视图是否有效,甚至在切换回流选项卡并恢复流时这段代码:
gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(self->video_sink), (guintptr) (id) self->ui_video_view);
gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(self->thumb_sinks[0]), (guintptr) (id) self->ui_thumb_views[0]);
gst_video_overlay_prepare_window_handle(GST_VIDEO_OVERLAY(self->thumb_sinks[0]));
gst_video_overlay_expose(GST_VIDEO_OVERLAY(self->thumb_sinks[0]));
gst_video_overlay_prepare_window_handle(GST_VIDEO_OVERLAY(self->video_sink));
gst_video_overlay_expose(GST_VIDEO_OVERLAY(self->video_sink));
我一直假设问题出在 glimagesink 元素中,因为推送样本返回,这向我表明 appsrc 接受了它,并且没有迹象表明缓冲区用完或丢弃样本。我觉得videoscale也不太可能是罪魁祸首,但我以前错了。
也许 glimagesink name=thumb_sink01 元素发生了一些愚蠢的事情。?.? 我还没有真正看过那个。
感谢任何人的任何反馈。
- 道格
解决方案
我对删除 glimagesink 并直接写入窗口句柄的最后评论看起来像是要走的路,而且总体上看起来效果更好。
从“new-sample”回调中接收到的 appsink 示例内存缓冲区中获取原始 RGB 解码帧,并从中创建一个 UIImage 并将 UIImageView.image 设置为 UIImage 作品。
如果对其他人有用,则可以使用一些伪代码示例进行转换(尽管在线提供了大量示例):
// Create this once before passing any image frames.
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
data->img_ctx = CGBitmapContextCreate(img_buff, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
// Use this for converting decoded RGB image frames to UIImage's
dispatch_async(dispatch_get_main_queue(), ^{
CGImageRef imgRef = CGBitmapContextCreateImage(data->img_ctx);
data->the_img = [[UIImage alloc] initWithCGImage: imgRef];
CGImageRelease(imgRef);
[data->ui_video_view setMyImage: (UIImage *)data->the_img];
[data->ui_video_view setNeedsDisplay];
});
// Edit: had problems with subclassing between Objective-C & Swift, so had to create this setter function to work around it.
-(void) setMyImage: (UIImage *) img {
super.image = img;
}
推荐阅读
- firebase - 在 Stateful Widget 中使用流提供程序来获取单个 Firestore 文档的数据
- asp.net - asp.net core 和 postgresql 迁移中的调用目标引发了异常
- amazon-s3 - 如何有效地检索具有特定数据的 kinesis 数据分析 S3 接收器文件
- sql - 有没有办法通过数组的内容过滤 BigQuery 中的行?
- java - 如果 xml 格式不正确,则 Java DOM xml 阅读器
- python - Windows 操作系统上的 python-snappy 安装错误
- java - 如何在 Hibernate 中获取具有偏移量和计数的行?
- c# - 如何使用蛋糕构建系统查找项目类型?
- regex - 如何使用 sed 替换 http 或 https?
- javascript - Discord.JS bulkDelete 14 天错误预防?