英文:
GStreamer: how to read mp4 frame by frame and extract capture (camera) time? Need to find closest to given ts frame
问题
给定一些时间戳(可能是秒或毫秒精度),我需要从 mp4 文件中提取与假定的摄像头时间戳(捕获时间,而不是 pts 或 dts)最接近的帧,那么更合适的流程是什么,以提取每个帧在其捕获时间戳内(类似于使用缓冲区中的 GetReferenceTimestampMeta)?考虑到我使用 gstreamer-sharp,我希望使用 appsink 事件,类似于:
private static void AppSink_NewSample(object o, NewSampleArgs args)
{
   
    if (o is AppSink aps)
    {
        var sample = aps.PullSample();
        var buf = sample.Buffer;
        buf.Map(out var info, MapFlags.Read);
 
        //application/x-rtp
        var tsMeta = buf.GetReferenceTimestampMeta();
        //NOTE tsMeta 不应为 null...
        //TODO 一些时间戳比较逻辑
        buf.Unmap(info);
    }
    Counter++;
}
简而言之,我需要遍历帧并基于某些条件(实际上是最接近给定时间戳的条件)选择其中之一。
提前感谢。
英文:
Given some timestamp (probably second or ms precision), I need to exctract closest frame
in mp4 file with assumed camera timestamp(captured time, not pts or dts) for each frame, what is a more appropriate pipeline to exctract each frame within it's captured timestamp (smth like to use GetReferenceTimestampMeta from buffer)? Given that I work via gstreamer-sharp I expect to use appsink events, smth like:
  private static void AppSink_NewSample(object o, NewSampleArgs args)
    {
       
        if (o is AppSink aps)
        {
            var sample = aps.PullSample();
            var buf = sample.Buffer;
            buf.Map(out var info, MapFlags.Read);
     
            //application/x-rtp
            var tsMeta = buf.GetReferenceTimestampMeta();
            //NOTE tsMeta shouldn't be null there...
            //TODO some timestamps compare logic
            buf.Unmap(info);
        }
        Counter++;
    }
Put it simple -- I need to iterate over frames and select one based on some condition (actually, closest to given timestamp).
Thanks in advance.
答案1
得分: 0
我找到了方法,它类似于:
var appSink = (AppSink)readerPipe.GetByName("my_appsink");
readerPipe.SetName("frame_stepper");
var q = readerPipe.SetState(State.Playing);
var step = 1;
while (step < frameNumber)
{
    appSink.PullSample();
    step++;
}
英文:
I found the way, it is smth like:
            var appSink = (AppSink) readerPipe.GetByName("my_appsink");
            readerPipe.SetName($"frame_stepper");
            var q = readerPipe.SetState(State.Playing);
            var step = 1; 
            while (step < frameNumber)
            {
                appSink.PullSample();
                step++;
            }
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论