首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从USB源播放原始h.264流(时间戳问题)

从USB源播放原始h.264流(时间戳问题)
EN

Stack Overflow用户
提问于 2021-03-17 17:17:16
回答 1查看 840关注 0票数 0

我正在处理一个实时视频源(无人机无线视频接收器),它通过USB输出一个原始的h.264视频流。我的目标是将它集成到安卓系统中的QGroundStation中,该系统有一个GStreamer管道。

我已经将接收到的USB数据的一部分转储到一个文件中,该文件完全可以使用vlc使用以下命令进行播放:

代码语言:javascript
复制
vlc -c dump.bin --demux h264

但是,如果我使用这个GStreamer管道回放它,播放速度就太快了(比如x10)。

代码语言:javascript
复制
gst-launch-1.0.exe filesrc location="dump.bin" ! h264parse ! avdec_h264 ! autovideosink

我使用appsrc将USB数据推入QGroundControl管道。视频播放,但是很多帧被丢弃,gstreamer抱怨数据包丢失,因为帧太晚了。

代码语言:javascript
复制
[...] 
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.404134207)
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.403025291)
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.401385832)
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.400435290)
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.399607540)
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.398911040)
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.398131998)
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.397308623)
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.396620290)
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.395761040)
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.395125498)
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.394197123)
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.393461831)
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.392803831)
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.391983373)
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.391033998)
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.389664914)
    W QGroundControl Daily: GStreamerAPILog: <amcvideodec-omxrkvideodecoderavc18> Frame is too late, dropping (deadline -0:00:00.388862831)
    W QGroundControl Daily: GStreamerAPILog: <h264parse53> broken/invalid nal Type: 1 Slice, Size: 38639 will be dropped
    W QGroundControl Daily: GStreamerAPILog: <h264parse53> broken/invalid nal Type: 1 Slice, Size: 37460 will be dropped
    W QGroundControl Daily: GStreamerAPILog: <h264parse53> broken/invalid nal Type: 1 Slice, Size: 46566 will be dropped
    W QGroundControl Daily: GStreamerAPILog: <h264parse53> broken/invalid nal Type: 1 Slice, Size: 36055 will be dropped
    W QGroundControl Daily: GStreamerAPILog: <h264parse53> broken/invalid nal Type: 1 Slice, Size: 43397 will be dropped
[...]

在仔细检查了我的转储之后,我意识到流缺少pts和dts信息(在基线h.264流中这似乎是常见的)。

代码语言:javascript
复制
ffprobe -show_frames dump.bin

[PACKET]
codec_type=video
stream_index=0
pts=N/A
pts_time=N/A
dts=N/A
dts_time=N/A
duration=48000
duration_time=0.040000
convergence_duration=N/A
convergence_duration_time=N/A
size=1843
pos=0
flags=K_
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=N/A
pts_time=N/A
dts=N/A
dts_time=N/A
duration=48000
duration_time=0.040000
convergence_duration=N/A
convergence_duration_time=N/A
size=16851
pos=1843
flags=K_
[/PACKET]

但很明显,持续时间信息就在那里。

USB端点读取512字节块(由于USB高速最大值).大容量端点的有效负载大小),并且有些传输比较小(400+字节长)。我无法检测NAL的开始/结束,因为它是一个不透明的连续字节流。(视频/x 264,流式格式=(字符串)字节流,alignment=none)

因此,我构建了一个appsrc来将视频流推到管道中,并试图盲目地对缓冲区进行时间戳,如下所示:

代码语言:javascript
复制
void _startFeed(GstElement *source, guint size, gpointer pContext) {
(void)pContext;

GstBuffer *pBuffer;
GstFlowReturn ret;
GstMapInfo map;
guint8 *pRaw;

GstClock *pClk = gst_element_get_clock(gPipeline);
GstClockTime absolute = gst_clock_get_time(pClk);
GstClockTime base = gst_element_get_base_time(gPipeline);
gst_object_unref(pClk);

pBuffer = gst_buffer_new_and_alloc(bufferSize);

// Timestamp the buffers
GST_BUFFER_PTS(pBuffer) = absolute - base;
GST_BUFFER_DTS(pBuffer) = GST_BUFFER_PTS(pBuffer);

gst_buffer_map(pBuffer, &map, GST_MAP_WRITE);

pRaw = (guint8 *)map.data;

fifo_pull(pRaw, size);  // This pulls up to 'size' bytes from the USB FIFO and copies it to pRaw

gst_buffer_unmap(pBuffer, &map);

g_signal_emit_by_name(gAppSrc, "push-buffer", pBuffer, &ret);

gst_buffer_unref(pBuffer);
}

..。但还是没有运气..。

通过使用以下管道将h.264流编码为RTP有效负载,然后使用一个caps过滤器指定目标帧,我的成功是有限的:

代码语言:javascript
复制
gst-launch-1.0.exe filesrc location="dump.bin" ! video/x-h264, stream-format=(string)byte-stream, alignment=none ! h264parse ! rtph264pay ! rtpjitterbuffer ! rtph264depay ! video/x-h264, stream-format=byte-stream, alignment=nal, framerate=(fraction)30/1 ! h264parse ! avdec_h264 ! autovideosink

我可以将其构建到QGroundControl中的C++中,但我不认为这是正确的方法,我不应该对目标框架做出任何假设,因为在这种情况下,它是30 fps,但它可能会动态变化。

所以,我的问题是:

  • 怎样才能在没有任何帧滴的情况下以正确的速度播放视频?
  • 是否合理或可能要求GStreamer根据使用标准流水线的数据包的持续时间信息生成PTS/DTS (没有B帧,所以PTS应该等于DTS)?

更新:

我已经尝试过一种已知的解决方法,用于从描述difference.

  • The +的here中插入PTS,但在我的示例中,PTS和DTS都不能在流中使用,因此它没有为这个特定的视频转储提供任何正确的帧,应该是29.97fps (NTSC)。我在视频图像中有一个运行计数器来验证它。正如您在我的ff探针输出中看到的那样,me.

  • Surprisingly,

  • 的duration_time信息显示为0.04s,对应于25 fps,这使人费解

VLC以正确的速度播放视频,并正确地猜测帧为29.97 fps (根据按下Ctrl+J的视频编解码信息窗口)

  • ,我注意到rtph264pay将生成丢失的时间戳,但猜测的帧为25 fps,因为数据包的duration_time字段表示
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-03-25 15:56:09

我使用了h.264流分析器,并意识到这个特定的流在SPS中没有VUI信息(因此解析器无法使用time_tick或time_scale信息来计算PTS)。

对我起作用的是在接收器上设置属性"sync“= false,以便在帧到达时立即呈现它们。不太理想,但我可以接受。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66678074

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档