简体   繁体   English

libvlc ffmpeg:在mpegts h264流中不查找

[英]libvlc ffmpeg: No seek in mpegts h264 stream

I am using ffmpeg to record video input from GDI (windows screen recorder) to view it later using VLC (via ActiveX plugin) + ffmpeg to decode it. 我正在使用ffmpeg录制来自GDI(Windows屏幕录像机)的视频输入,以便稍后使用VLC(通过ActiveX插件)+ ffmpeg对其进行解码。

Right now seeking in video is not working in VLC via plugin (which is critical). 目前,通过插件无法在视频中进行视频搜索(这很关键)。 VLC player itself provide seeking, but it is more like byte position seeking (on I- frames which are larger than other frames it makes larger steps on horizontal scroll and also there are no timestamps). VLC播放器本身提供搜索,但它更像字节位置搜索(在比其他帧大的I帧上,它在水平滚动时步长较大,并且没有时间戳记)。

Encoder is opened with next defaults: 将打开编码器,并带有下一个默认值:

avformat_alloc_output_context2(&outputContext, NULL, "mpegts", "test.mpg");
outputFormat = outputContext->oformat;
encoder = avcodec_find_encoder(AV_CODEC_ID_H264);
outputStream = avformat_new_stream(outputContext, encoder);
outputStream->id = outputContext->nb_streams - 1;
encoderContext = outputStream->codec;
encoderContext->bit_rate = bitrate;   // 800000 by default
encoderContext->rc_max_rate = bitrate;
encoderContext->width = imageWidth;   // 1920
encoderContext->height = imageHeight; // 1080
encoderContext->time_base.num = 1;
encoderContext->time_base.den = fps;  // 25 by default
encoderContext->gop_size = fps;
encoderContext->keyint_min = fps;
encoderContext->max_b_frames = 0;
encoderContext->pix_fmt = AV_PIX_FMT_YUV420P;
outputStream->time_base = encoderContext->time_base;
avcodec_open2(encoderContext, encoder, NULL);

Recording is done this way: 记录是通过以下方式完成的:

// my impl of GDI recorder, returning AVFrame with only data and linesize filled.
AVFrame* tmp_frame = impl_->recorder->acquireFrame();

// converting RGB -> YUV420
sws_scale(impl_->scaleContext, tmp_frame->data, tmp_frame->linesize, 0, impl_->frame->height, impl_->frame->data, impl_->frame->linesize);

// pts variable is calculated by using QueryPerformanceCounter form WinAPI. It is strictly increasing
impl_->frame->pts = pts;

avcodec_encode_video2(impl_->encoderContext, impl_->packet, impl_->frame, &out_size);

if (out_size) {
     impl_->packet->pts = pts;
     impl_->packet->dts = pts;
     impl_->packet->duration = 1; // here it is! It is set but has no effect
     av_packet_rescale_ts(impl_->packet, impl_->encoderContext->time_base, impl_->outputStream->time_base);
     // here pts = 3600*pts, dts = 3600*pts, duration = 3600 what I consider to be legit in terms of milliseconds
     impl_->packet->stream_index = impl_->outputStream->index;
     av_interleaved_write_frame(impl_->outputContext, impl_->packet);
     av_packet_unref(impl_->packet);
     out_size = 0;
}

ffprobe is providing next info on frames: ffprobe提供有关框架的下一个信息:

[FRAME]
media_type=video
stream_index=0
key_frame=1
pkt_pts=3600
pkt_pts_time=0:00:00.040000
pkt_dts=3600
pkt_dts_time=0:00:00.040000
best_effort_timestamp=3600
best_effort_timestamp_time=0:00:00.040000
pkt_duration=N/A
pkt_duration_time=N/A
pkt_pos=564
pkt_size=97.018555 Kibyte
width=1920
height=1080
pix_fmt=yuv420p
sample_aspect_ratio=N/A
pict_type=I
coded_picture_number=0
display_picture_number=0
interlaced_frame=0
top_field_first=0
repeat_pict=0
[/FRAME]

I believe that problem is in pkt_duration variable, though it was set. 我相信问题出在pkt_duration变量中,尽管它已设置。 What I am doing wrong in recording so I can't seek in video? 我在录制时做错了什么,所以无法在视频中搜索?

PS on other videos (also h264) seeking is working in ActiveX VLC plugin. 在其他视频(也为h264)上搜索的PS正在ActiveX VLC插件中运行。

What is definitely wrong, is: 绝对错误的是:

impl_->packet->pts = pts;
impl_->packet->dts = pts;

PTS and DTS are not equal! PTS和DTS不相等! They could be if you would have only I-frames, which is not the case here. 如果您只有I帧,则可能是这种情况,这里不是这种情况。 Also, your comment says: pts variable is calculated by using QueryPerformanceCounter form WinAPI . 另外,您的评论还说: pts变量是通过使用QueryPerformanceCounter形式WinAPI计算的 If your frame rate is constant, and I believe it is, then you don't need QueryPerformanceCounter API. 如果您相信帧速率是恒定的,并且我相信它是恒定的,那么您就不需要QueryPerformanceCounter API。 PTS is usually in 90kHz units. PTS通常以90kHz为单位。 The duration of 1 frame expressed in 90kHz is calculated like this: 以90kHz表示的1帧的持续时间计算如下:

90000 x denominator / numerator 90000 x分母/分子

If fps is 25 then numerator is 25 and denominator is 1. For 29.97 fps the numerator is 30000 and denominator is 1001. Each new frame's PTS should be increased for that amount (unless you have dropped frames). 如果fps为25,则分子为25,分母为1。对于29.97 fps,分子为30000,分母为1001。每个新帧的PTS都应增加该数量(除非您丢弃了帧)。 Regarding the DTS, the encoder should provide that value. 关于DTS,编码器应提供该值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM