C# 流中对多路复用器的非单调递增dts

C# 流中对多路复用器的非单调递增dts,c#,ffmpeg,accord.net,C#,Ffmpeg,Accord.net,我只是想从一个缓冲区中保存相同的视频帧,在那里我正确地保存了位图帧和帧的时间戳 writer1 = new VideoFileWriter(); this.writer1.Width = this.videoSourceEndo.VideoResolution.FrameSize.Width; this.writer1.Height = this.videoSourceEndo.VideoResolution.FrameSize.Height; this.writer1.VideoCodec =

我只是想从一个缓冲区中保存相同的视频帧,在那里我正确地保存了位图帧和帧的时间戳

writer1 = new VideoFileWriter();
this.writer1.Width = this.videoSourceEndo.VideoResolution.FrameSize.Width;
this.writer1.Height = this.videoSourceEndo.VideoResolution.FrameSize.Height;
this.writer1.VideoCodec = VideoCodec.H264;
this.writer1.BitRate = (this.videoSourceEndo.VideoResolution.FrameSize.Height * this.videoSourceEndo.VideoResolution.FrameSize.Width * 30);

this.writer1.VideoOptions["preset"] = "superfast";
this.writer1.VideoOptions["tune"] = "zerolatency";

writer1.Open("test_HDMI.mp4");

但在visual studio上,而不是在第一帧上,我遇到了以下错误: Accord.Video.VideoException:'写入视频帧时出错。错误-22:参数无效。有关更多详细信息,请参阅控制台输出。”

在控制台上: 应用程序向流0:512>=512中的多路复用器提供了无效的、非单调递增的dts

我不知道原因是什么,因为在调试时,所有的值似乎都是正确的。 如果您需要更多的代码,请告诉我。好的,我会放在这里。 首先,VideoStream->time_base:1/15360从何而来,30fps应该是1000/30000,29.97 fps应该是1001/30000

第二,您的pts/dts和帧持续时间计算有问题。如您所见,最后两个pts/dts值是相同的

对于数据包持续时间,我假设fps为常数,通常应使用这些预先计算的值或与您的值一起检查作为参考:

fps     duration (same unit as AVPacket::duration)
23.98   2086
24.00   2000
25.00   2000
29.97   2068
30.00   2000
50.00   1000
59.94   1016
60.00   1000
对于手动计算pts/dts: 这是我使用的C++函数:

static void write_video_pts(EncoderContext *ectx, AVPacket *pkt)
{
    pkt->pts          = ectx->video_pts; /* this is to keep next pts value, same unit as AVPacket::pts */
    ectx->video_pts  += ectx->frame_duration; /* check above table for ectx->frame_duration value */
    pkt->dts          = pkt->pts;
    pkt->duration     = ectx->frame_duration; /* check above table for ectx->frame_duration value */
    pkt->stream_index = ectx->VideoStream->index; /* AVStream */
}
当从原始源(如您的源代码)手动编码时,这些方法肯定有效。当然不是为了转码


希望这能有所帮助。

我假设您正确设置了编解码器/流时间,但我在这里没有看到。所以你的问题就在这里endoFrameBuffer.getframetimeendoFrameBuffer.Tail让我们看看代码endoFrameBuffer只是一个带有位图图像的环形缓冲区,以及正确的timespan:public timespan getframetimeint index{return _timeBuffer[index];}设置值,我只添加了一个新元素,如下所示:endoFrameBuffer.EnqueueeventArgs.Frame,DateTime.Now-\u firstFrameTime.Value;当触发newframe事件时。然后在另一个线程上,我只是从RingBuffer记录每一帧。让我直接问你,视频流的fps是多少,因为pts=512对我来说是不寻常的。getFrameTime方法返回的是pts值吗?视频流大约是aprox。每秒30帧。getFrameTime返回帧和接收到的第一帧之间的时间间隔差我无法理解为什么会发生这种情况。使用Accord框架,我只需要传递这些值,它们似乎是正确的。。。
static void write_video_pts(EncoderContext *ectx, AVPacket *pkt)
{
    pkt->pts          = ectx->video_pts; /* this is to keep next pts value, same unit as AVPacket::pts */
    ectx->video_pts  += ectx->frame_duration; /* check above table for ectx->frame_duration value */
    pkt->dts          = pkt->pts;
    pkt->duration     = ectx->frame_duration; /* check above table for ectx->frame_duration value */
    pkt->stream_index = ectx->VideoStream->index; /* AVStream */
}